home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / languags / zc.2 < prev    next >
Text File  |  1989-03-08  |  64KB  |  3,694 lines

  1. Path: xanth!nic.MR.NET!csd4.milw.wisc.edu!mailrus!bbn!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i029:  zc - c compiler, Part02/04
  5. Message-ID: <12043@swan.ulowell.edu>
  6. Date: 8 Mar 89 03:03:15 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 3683
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery)
  12. Posting-number: Volume 89, Issue 29
  13. Archive-name: languages/zc.2
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    d2.c
  23. #    decl.c
  24. #    expr.c
  25. #    fix.c
  26. #    fun.c
  27. #    g2.c
  28. # This archive created: Tue Mar  7 21:49:30 1989
  29. cat << \SHAR_EOF > d2.c
  30. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  31.  *
  32.  * Permission is granted to anyone to use this software for any purpose
  33.  * on any computer system, and to redistribute it freely, with the
  34.  * following restrictions:
  35.  * 1) No charge may be made other than reasonable charges for reproduction.
  36.  * 2) Modified versions must be clearly marked as such.
  37.  * 3) The authors are not responsible for any harmful consequences
  38.  *    of using this software, even if they result from defects in it.
  39.  *
  40.  *    d2.c
  41.  *
  42.  *    Declaration subroutines
  43.  *
  44.  *    Mostly routines for initializations
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include "param.h"
  49. #include "tok.h"
  50. #include "nodes.h"
  51. #include "cookie.h"
  52.  
  53. #if MMCC
  54. overlay "pass2"
  55. #endif
  56.  
  57. extern NODEP cur;
  58. extern NODEP symtab[];
  59. extern level;
  60.  
  61. extern int oflags[];
  62. #define debugi    oflags['i'-'a']
  63.  
  64. su_size(lp, cp, xp, isunion)
  65. register long *lp;
  66. char *cp;
  67. register NODE *xp;
  68. {
  69.     long sz;
  70.     char al;
  71.  
  72.     sz = xp->n_tptr->t_size;
  73.     al = xp->n_tptr->t_aln;
  74.     if (isunion) {
  75.         *lp = *lp > sz ? *lp : sz;
  76.     } else {
  77.         while (al & (*lp)) {    /* align new field */
  78.             (*lp)++;
  79.             xp->e_offs++;
  80.         }
  81.         *lp += sz;
  82.     }
  83.     *cp = *cp > al ? *cp : al;
  84. }
  85.  
  86. lc_size(lp, rp, xp)
  87. register long *lp;
  88. int *rp;
  89. register NODE *xp;
  90. {
  91.     long sz;
  92.     char al;
  93.     long arg_size();
  94.  
  95.     if (level > 1 && xp->e_sc == K_REGISTER) {
  96.         if (lc_reg(rp, xp))
  97.             return;
  98.         else
  99.             xp->e_sc = K_AUTO;
  100.     }
  101.     if (xp->e_sc == K_AUTO || level == 1) {
  102.         sz = xp->n_tptr->t_size;
  103.         al = xp->n_tptr->t_aln;
  104.         while (al & (*lp)) {    /* align new field */
  105.             (*lp)++;
  106.             xp->e_offs++;
  107.         }
  108.         if (level == 1) {
  109.             sz = arg_size(sz,xp);
  110.             xp->e_offs += ARG_BASE + *lp;
  111.         }
  112.         *lp += sz;
  113.         if (level != 1)
  114.             xp->e_offs = LOC_BASE - *lp;
  115.     }
  116. }
  117.  
  118. su_fld(lp, alp, xp, fldw, fop)
  119. register long *lp;
  120. char *alp;
  121. register NODE *xp;
  122. int *fop;
  123. {
  124.     if (*alp < ALN_I)
  125.         *alp = ALN_I;
  126.     if (fldw == 0) {
  127.         afterfld(lp, fop);
  128.         return;
  129.     }
  130.     if (fldw + *fop > 8*SIZE_I)
  131.         afterfld(lp, fop);
  132.     if (xp) {
  133.         xp->e_fldw = fldw;
  134.         xp->e_fldo = *fop;
  135.     }
  136.     *fop += fldw;
  137. }
  138.  
  139. afterfld(szp, fop)
  140. long *szp;
  141. int *fop;
  142. {
  143.     if (*fop) {
  144.         *szp += SIZE_I;
  145.         *fop = 0;
  146.     }
  147. }
  148.  
  149. ok_gsh(sc, np)
  150. NODE *np;
  151. {
  152.     if (sc == K_REGISTER || sc == K_AUTO) {
  153.         error("reg/auto outside fun");
  154.         return 0;
  155.     }
  156.     return ok_ty(np, NULL);
  157. }
  158.  
  159. ok_gx(np, endp)
  160. NODEP np, endp;
  161. {
  162.     if (np)
  163.         return ok_ty(np->n_tptr, endp);
  164.     return 0;
  165. }
  166.  
  167. ok_lsh(sc, np)
  168. NODE *np;
  169. {
  170.     return ok_ty(np, NULL);
  171. }
  172.  
  173. arytoptr(np)
  174. NODEP np;
  175. {
  176.     NODEP tp = np->n_tptr;
  177.     NODEP copyone();
  178.  
  179.     if (np->n_flags & N_COPYT) {    /* cant change if a dupl. */
  180.         tp = copyone(tp);
  181.         np->n_tptr = tp;
  182.         np->n_flags &= ~N_COPYT;
  183.     }
  184.     tp->t_token = STAR;
  185.     strcpy(tp->n_name, "Aptr to");
  186. }
  187.  
  188. ok_lx(np,endp)
  189. NODEP np, endp;
  190. {
  191.     if (np) {
  192.         if (level == 1 && np->n_tptr->t_token == '[')
  193.             arytoptr(np);
  194.         return ok_ty(np->n_tptr, endp);
  195.     }
  196.     return 0;
  197. }
  198.  
  199. ok_suh(np)
  200. NODEP np;
  201. {
  202.     return 1;
  203. }
  204.  
  205. ok_sux(np, endp)
  206. NODEP np, endp;
  207. {
  208.     if (np)
  209.         return ok_ty(np->n_tptr, endp);
  210.     return 0;
  211. }
  212.  
  213. ok_enx(np, endp)
  214. NODEP np, endp;
  215. {
  216.     if (np && np->n_tptr == endp)   /* no modifiers */
  217.         return 1;
  218.     return 0;
  219. }
  220.  
  221. ok_cast(np, endp)
  222. NODEP np, endp;
  223. {
  224.     if (np)
  225.         return ok_ty(np, endp);
  226.     return 0;
  227. }
  228.  
  229. ok_ty(np, endp)
  230. register NODEP np, endp;
  231. {
  232.     NODEP child;
  233.     long csize;
  234.     long conlval();
  235.  
  236.     if (np == endp)
  237.         return 1;
  238.     child = np->n_tptr;
  239.     if (child) {
  240.         if (ok_ty(child, endp) == 0)
  241.             return 0;
  242.         csize = child->t_size;
  243.     }
  244.  
  245.     switch (np->t_token) {
  246.     case STAR:
  247.         np->t_size = SIZE_P;
  248.         np->t_aln = ALN_P;
  249.         break;
  250.     case '(':
  251.         /* size 0 okay - fun ret void */
  252.         if (child->t_token == '[') {
  253.             error("bad func");
  254.             return 0;
  255.         }
  256.         /* size 0 */
  257.         break;
  258.     case '[':
  259.         if (csize == 0) {
  260.             error("bad array");
  261.             return 0;
  262.         }
  263.         if (np->n_right) {
  264.             csize *= conlval(np->n_right);
  265.             np->n_right = NULL;
  266.             np->t_size = csize;
  267.         }
  268.         np->t_aln = child->t_aln;
  269.         break;
  270.     default:
  271.         return 1;
  272.     }
  273.     return 1;
  274. }
  275.  
  276. ok_revx(rv,forcast)
  277. NODEP rv;
  278. {
  279.     if (rv == NULL)
  280.         return 1;
  281.     if (forcast == 0 && rv->e_token != ID) {
  282.         error("need ID");
  283.         return 0;
  284.     }
  285.     if (forcast && rv->e_token == ID) {
  286.         error("ID in cast");
  287.         return 0;
  288.     }
  289.     return 1;
  290. }
  291.  
  292. opt_ginit(xp)
  293. NODEP xp;
  294. {
  295.     if (xp->e_token != ID)
  296.         return;
  297.     if (xp->n_tptr->t_token == '(')
  298.         return;
  299.     switch (xp->e_sc) {
  300.     case K_STATIC:
  301.     case HERE_SC:
  302.         if (cur->e_token == '=') {
  303.             out_gv(xp, 0);   /* place in data segment */
  304.             fadvnode();
  305.             g_init(xp->n_tptr);
  306.         } else
  307.             out_gv(xp, 1);   /* place in BSS segment */
  308.         break;
  309. /* ? added external case ? */
  310.     case K_EXTERN:
  311.         out_gv(xp,0);
  312.     }
  313. }
  314.  
  315. opt_linit(xp)
  316. NODEP xp;
  317. {
  318.     if (xp->e_token != ID)
  319.         return;
  320.     if (xp->n_tptr->t_token == '(')
  321.         return;
  322.     switch (xp->e_sc) {
  323.     case K_STATIC:
  324.         if (cur->e_token == '=') {
  325.             out_gv(xp, 0);
  326.             fadvnode();
  327.             g_init(xp->n_tptr);
  328.         } else
  329.             out_gv(xp, 1);
  330.         to_text();
  331.         break;
  332.     case K_AUTO:
  333.     case K_REGISTER:
  334.         if (cur->e_token == '=')
  335.             a_init(xp);
  336.         break;
  337.     }
  338. }
  339.  
  340. a_init(op)
  341. NODEP op;
  342. {
  343.     register NODEP np, xp;
  344.     NODEP assignx(), copynode();
  345.  
  346.     np = cur;  advnode();
  347.     xp = assignx();
  348.     op = copynode(op);
  349.     np->n_left = op;
  350.     np->n_right = xp;
  351.     np->e_type = E_BIN;
  352.     do_expr(np, FORSIDE);
  353.     return;
  354. }
  355.  
  356. opt_enval(intp)
  357. int *intp;
  358. {
  359.     NODEP np;
  360.     NODEP questx();
  361.  
  362.     if (cur->e_token == '=') {
  363.         fadvnode();
  364.         np = questx();
  365.         *intp = conxval(np);
  366.         return;
  367.     }
  368. }
  369.  
  370. opt_field(xp,wdp,isunion)
  371. NODE *xp;
  372. int *wdp;
  373. {
  374.     NODEP np;
  375.     NODEP questx();
  376.     int i;
  377.  
  378.     *wdp = -1;
  379.     if (isunion) return;
  380.     if (cur->e_token == ':') {
  381.         fadvnode();
  382.         np = questx();
  383.         i = conxval(np);
  384.         if (i > 8*SIZE_I) {
  385.             error("field too big");
  386.             i = 8*SIZE_I;
  387.         }
  388.         if (xp) {
  389.             if (i <= 0 || bad_fty(xp->n_tptr)) {
  390.                 error("bad field");
  391.                 return;
  392.             }
  393.         } else if (i < 0) {
  394.             error("neg field width");
  395.             return;
  396.         }
  397.         *wdp = i;
  398.         return;
  399.     }
  400. }
  401.  
  402. bad_fty(tp)
  403. NODEP tp;
  404. {
  405.     int tok;
  406.  
  407.     tok = tp->t_token;
  408.     if (tok == K_INT || tok == K_UNSIGNED)
  409.         return 0;
  410.     return 1;
  411. }
  412.  
  413. field(xp, wd, ofp)
  414. NODEP xp;
  415. int *ofp;
  416. {
  417. }
  418.  
  419. NODEP
  420. def_type()
  421. {
  422.     NODEP bas_type();
  423.  
  424.     return bas_type(K_INT);
  425. }
  426.  
  427. #define NSC    LAST_SC-FIRST_SC+1
  428. #define NBAS    LAST_BAS-FIRST_BAS+1
  429.  
  430. NODE basics[NBAS];
  431. NODE str_ptr, fun_int;
  432.  
  433. struct bt {
  434.     char    *name;
  435.     int    size;
  436.     char    align;
  437. } btbl[] = {
  438.     {"Uchar",       SIZE_C, ALN_C},
  439.     {"Ulong",       SIZE_L, ALN_L},
  440.     {"Long",        SIZE_L, ALN_L},
  441.     {"Short",       SIZE_S, ALN_S},
  442.     {"Uns",         SIZE_U, ALN_U},
  443.     {"Int",         SIZE_I, ALN_I},
  444.     {"Char",        SIZE_C, ALN_C},
  445.     {"Float",       SIZE_F, ALN_F},
  446.     {"Dbl",         SIZE_D, ALN_D},
  447.     {"Void",        0},
  448. };
  449.  
  450. NODEP
  451. bas_type(btype)
  452. {
  453.     NODEP rv;
  454.     static once = 0;
  455.  
  456.     if (once == 0) {
  457.         once++;
  458.  
  459.         sprintf(str_ptr.n_name, "Ptr to");
  460.         str_ptr.t_token = STAR;
  461.         str_ptr.n_tptr = bas_type(K_CHAR);
  462.         str_ptr.n_flags = N_COPYT;
  463.         str_ptr.t_size = SIZE_P;
  464.         str_ptr.t_aln = ALN_P;
  465.  
  466.         sprintf(fun_int.n_name, "Fun ret");
  467.         fun_int.t_token = '(';
  468.         fun_int.n_tptr = bas_type(K_INT);
  469.         fun_int.n_flags = N_COPYT;
  470.     }
  471.     if (btype == SCON)
  472.         return &str_ptr;
  473.     else if (btype == '(')
  474.         return &fun_int;
  475.     rv = &basics[btype-FIRST_BAS];
  476.     if (rv->t_token == 0) {
  477.         rv->t_token = btype;
  478.         rv->t_size = btbl[btype-FIRST_BAS].size;
  479.         rv->t_aln = btbl[btype-FIRST_BAS].align;
  480.         sprintf(rv->n_name, btbl[btype-FIRST_BAS].name);
  481.     }
  482.     return rv;
  483. }
  484.  
  485. /* new function name seen in expr */
  486. NODEP
  487. new_fun(op)
  488. NODE *op;
  489. {
  490.     NODEP np;
  491.     NODEP copyone();
  492.  
  493.     /* we know left, right and tptr are NULL */
  494.     np = copyone(op); /* ID node */
  495.     np->n_tptr = bas_type('(');
  496.     np->n_flags = N_COPYT;
  497.     np->e_sc = K_EXTERN;
  498.     new_sym(symtab, np);
  499.     return np;
  500. }
  501.  
  502. /* declare arg name as int */
  503. def_arg(listpp, op)
  504. NODE **listpp, *op;
  505. {
  506.     register NODEP np;
  507.     NODEP copyone();
  508.  
  509.     np = copyone(op);
  510.     np->n_tptr = bas_type(K_INT);
  511.     np->n_flags = N_COPYT;
  512.     np->e_sc = K_AUTO;
  513.     new_sym(listpp, np);
  514. }
  515.  
  516. /* initialize 0 or 1 thing of any type (tp) */
  517. g_init(tp)
  518. register NODEP tp;
  519. {
  520.     int nsee;
  521.     long sz;
  522.     int oldsize;
  523.     int seebr = 0;
  524.  
  525.     if (cur->e_token == SCON &&
  526.            tp->t_token == '[' &&
  527.            tp->n_tptr->t_token == K_CHAR) { /* hack for SCON ary */
  528.             nsee = out_scon(cur);
  529.             fadvnode();
  530.             a_fix(tp, nsee);
  531.             return 1;
  532.     }
  533.  
  534.     if (cur->e_token == '{') {
  535.         fadvnode();
  536.         seebr = 1;
  537.     }
  538.  
  539.     switch (tp->t_token) {
  540.     case '[':
  541.         if (tp->t_size)
  542.             oldsize = tp->t_size / tp->n_tptr->t_size;
  543.         else
  544.             oldsize = 0;
  545.         nsee = inita(tp->n_tptr, oldsize);
  546.         if (nsee)
  547.             a_fix(tp, nsee);
  548.         break;
  549.     case K_STRUCT:
  550.         o_aln(tp->t_aln);
  551.         nsee = inits(tp->n_right);
  552.         break;
  553.     case K_UNION:
  554.         o_aln(tp->t_aln);
  555.         nsee = g_init(tp->n_right->n_tptr);
  556.         if (nsee) {
  557.             sz = tp->t_size - tp->n_right->n_tptr->t_size;
  558.             if (sz)
  559.                 o_nz(sz, 0);
  560.         }
  561.         break;
  562.     default:
  563.         nsee = init1(tp);
  564.         break;
  565.     }
  566.  
  567.     if (seebr) {
  568.         if (cur->e_token == ',')
  569.             fadvnode();
  570.         eat('}');
  571.     }
  572.     return nsee ? 1 : 0;
  573. }
  574.  
  575. /* initialize one (or 0) scalar to an expr */
  576. init1(tp)
  577. register NODEP tp;
  578. {
  579.     NODEP xp;
  580.     NODEP assignx();
  581.  
  582.     if (debugi) {
  583.         printf("init1");
  584.         printnode(tp);
  585.     }
  586.     xp = assignx();
  587.     if (xp) {
  588.         if (debugi)
  589.             printnode(xp);
  590.         o_vinit(tp, xp);
  591.         return 1;
  592.     } else
  593.         return 0;
  594. }
  595.  
  596. /* set array size or fill array with zeros */
  597. a_fix(tp, nsee)
  598. register NODEP tp;
  599. {
  600.     int oldsize;
  601.  
  602.     if (tp->t_size) {
  603.         oldsize = tp->t_size / tp->n_tptr->t_size;
  604.         if (oldsize > nsee) {
  605.             o_nz(tp->n_tptr->t_size * (oldsize-nsee),
  606.                 tp->n_tptr->t_aln);
  607.         } else if (oldsize < nsee) {
  608.             error("too many init exprs");
  609.         }
  610.     } else
  611.         tp->t_size = nsee * tp->n_tptr->t_size;
  612. }
  613.  
  614. /* initialize up to max items of type tp */
  615. /* if max is 0, any number is okay */
  616.  
  617. inita(tp, maxi)
  618. NODEP tp;
  619. {
  620.     int nsee;
  621.  
  622.     nsee = g_init(tp);
  623.     if (nsee == 0)
  624.         return 0;
  625.  
  626.     while (cur->e_token == ',') {
  627.         if (nsee == maxi)
  628.             break;
  629.         fadvnode();
  630.         nsee += g_init(tp);
  631.     }
  632.     return nsee;
  633. }
  634.  
  635. /* initialize (possible) structure */
  636. inits(np)
  637. register NODEP np;
  638. {
  639.     int see1;
  640.  
  641.     see1 = g_init(np->n_tptr);
  642.     if (see1 == 0)
  643.         return 0;
  644.  
  645.     while (np->n_next) {
  646.         np = np->n_next;
  647.         if (cur->e_token == ',') {
  648.             fadvnode();
  649.             see1 = g_init(np->n_tptr);
  650.         } else
  651.             see1 = 0;
  652.         if (see1 == 0)
  653.             z_init(np->n_tptr);
  654.     }
  655.  
  656.     return 1;
  657. }
  658.  
  659. z_init(tp)
  660. register NODEP tp;
  661. {
  662.     switch (tp->t_token) {
  663.     case '[':
  664.     case K_STRUCT:
  665.     case K_UNION:
  666.         o_nz(tp->t_size, tp->t_aln);
  667.         break;
  668.     default:
  669.         out_zi(tp);
  670.     }
  671. }
  672. SHAR_EOF
  673. cat << \SHAR_EOF > decl.c
  674. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  675.  *
  676.  * Permission is granted to anyone to use this software for any purpose
  677.  * on any computer system, and to redistribute it freely, with the
  678.  * following restrictions:
  679.  * 1) No charge may be made other than reasonable charges for reproduction.
  680.  * 2) Modified versions must be clearly marked as such.
  681.  * 3) The authors are not responsible for any harmful consequences
  682.  *    of using this software, even if they result from defects in it.
  683.  *
  684.  *    decl.c
  685.  *
  686.  *    Do all declarations
  687.  *
  688.  *    Currently,
  689.  *        struct tags are local
  690.  *        struct members are tied to the struct
  691.  *        enum tags are ignored
  692.  *        enum members are local
  693.  */
  694.  
  695. #include <stdio.h>
  696. #include "param.h"
  697. #include "tok.h"
  698. #include "nodes.h"
  699.  
  700. extern NODE *cur;
  701. extern level;
  702.  
  703. NODEP symtab[NHASH], tagtab;
  704. extern NODE *blktab;
  705.  
  706. NODEP alltags(), allsyms(), llook(), hlook();
  707.  
  708. extern int oflags[];
  709. #define debug    oflags['v'-'a']
  710.  
  711. /* look for global data decls
  712.     return when see something weird
  713.     return last ID declared */
  714. NODEP
  715. glb_decls()
  716. {
  717.     register NODEP head, xp;
  718.     NODEP d_type(), def_type(), d_declr();
  719.     int sclass;
  720.  
  721.     for(;;) {
  722.         sclass = d_scl(HERE_SC);
  723.         head = d_type();
  724.         if (head == NULL)
  725.             head = def_type();
  726.         if (ok_gsh(sclass, head) == 0)
  727.             continue;
  728.     more:
  729.         xp = d_declr(head,0);
  730.         if (ok_gx(xp,head)) {
  731.             xp->e_sc = sclass;
  732.             opt_ginit(xp);
  733.             new_sym(symtab,xp);
  734.             if (xp->n_tptr->t_token == '(') {       /* func */
  735.                 if (cur->e_token == ',' ||
  736.                     cur->e_token == ';')
  737.                     fix_fun(xp);
  738.                 else
  739.                     return xp;
  740.             }
  741.         }
  742.  
  743.         if (cur->e_token == ',') {
  744.             fadvnode();
  745.             goto more;
  746.         }
  747.  
  748.         if (cur->e_token == ';') {
  749.             fadvnode();
  750.         } else
  751.             return NULL;
  752.     }
  753. }
  754.  
  755. /* do local or arg decls
  756.     return 1 if see something */
  757. loc_decls()
  758. {
  759.     register NODEP head, xp;
  760.     NODEP d_type(), def_type(), d_declr();
  761.     int sclass;
  762.     int regs;
  763.     long size;
  764.     int rv = 0;
  765.  
  766.     size = level > 2 ? blktab->n_next->b_size : 0;
  767.     regs = level > 1 ? blktab->n_next->b_regs : 0;
  768.     while (is_ty_start()) {
  769.         rv++;
  770.         sclass = d_scl(K_AUTO);
  771.         head = d_type();
  772.         if (head == NULL)
  773.             head = def_type();
  774.         if (ok_lsh(sclass, head) == 0)
  775.             continue;
  776.     more:
  777.         xp = d_declr(head,0);
  778.         if (ok_lx(xp,head)) {
  779.             xp->e_sc = sclass;
  780.             if (level > 1)  /* not args */
  781.                 lc_size(&size, ®s, xp);
  782.             new_sym(&blktab->b_syms,xp);
  783.             fix_fun(xp);
  784.             opt_linit(xp,sclass);
  785.         }
  786.  
  787.         if (cur->e_token == ',') {
  788.             fadvnode();
  789.             goto more;
  790.         }
  791.  
  792.         if (cur->e_token == ';') {
  793.             fadvnode();
  794.         } else {
  795.             error("expect ;");
  796.             return 1;
  797.         }
  798.     }
  799.     while (STACKALN & size)
  800.         size++;
  801.     blktab->b_size = size;
  802.     blktab->b_regs = regs;
  803.     return rv;
  804. }
  805.  
  806. /* Decls inside Struct/Union */
  807. su_decls(listpp, isunion, sizep, alnp)
  808. NODEP *listpp;
  809. long *sizep;
  810. char *alnp;
  811. {
  812.     register NODEP head, xp;
  813.     NODEP d_type(), d_declr();
  814.     long size;
  815.     char aln;
  816.     int fldw, fldoff;
  817.  
  818.     aln = 0;
  819.     size = 0;
  820.     fldoff = 0;
  821.     for(;;) {
  822.         head = d_type();
  823.         if (head == NULL)
  824.             goto out;
  825.         if (ok_suh(head) == 0)
  826.             continue;
  827.     more:
  828.         xp = d_declr(head,0);
  829.         opt_field(xp,&fldw,isunion);
  830.         if (ok_sux(xp,head)) {
  831.             if (fldw > 0) { /* handle field */
  832.                 su_fld(&size,&aln,xp,fldw,&fldoff);
  833.                 xp->e_offs = size;
  834.             } else {        /* handle non-field */
  835.                 afterfld(&size,&fldoff);
  836.                 xp->e_offs = isunion ? 0 : size;
  837.                 su_size(&size,&aln,xp,isunion);
  838.             }
  839.             new_sym(listpp,xp);
  840.             listpp = &xp->n_next;
  841.         } else if (fldw == 0) {
  842.             afterfld(&size, &fldoff);
  843.         }
  844.  
  845.         if (cur->e_token == ',') {
  846.             fadvnode();
  847.             goto more;
  848.         }
  849.  
  850.         if (cur->e_token == ';') {
  851.             fadvnode();
  852.         } else
  853.             goto out;
  854.     }
  855. out:
  856.     afterfld(&size,&fldoff);
  857.     while (aln & size)
  858.         size++;
  859.     *sizep = size;
  860.     *alnp = aln;
  861.     return;
  862. }
  863.  
  864. /* Decls inside Enum */
  865. en_decls()
  866. {
  867.     register NODEP head, xp;
  868.     NODEP bas_type(), d_declr();
  869.     int curval = 0;
  870.  
  871.     for(;;) {
  872.         head = bas_type(K_INT);
  873.     more:
  874.         xp = d_declr(head,0);
  875.         if (ok_enx(xp,head)) {
  876.             opt_enval(&curval);
  877.             xp->e_ival = curval++;
  878.             xp->e_sc = ENUM_SC;
  879.             new_sym(level ? blktab->b_syms : (NODE *)symtab,
  880.                 xp);
  881.         }
  882.  
  883.         if (cur->e_token == ',') {
  884.             fadvnode();
  885.             goto more;
  886.         }
  887.  
  888.         return;
  889.     }
  890. }
  891.  
  892. /*
  893.  * called from expr.c, make a cast
  894.  * only called if is_ty_start();
  895.  */
  896. NODE *
  897. makecast()
  898. {
  899.     NODEP head, xp;
  900.     register NODEP np;
  901.     NODEP d_type(), d_declr(), def_type();
  902.  
  903.     head = d_type();        /* we know this is not NULL */
  904.     xp = d_declr(head, 1);
  905.     if (ok_cast(xp,head) == 0) {
  906.         xp = def_type();        /* return cast to INT */
  907.     }
  908.     np = allocnode();
  909.     np->e_token = TCONV;
  910.     np->n_tptr = xp;
  911.     if (xp == head)
  912.         np->n_flags |= N_COPYT;
  913.     if (debug) {
  914.         printf("Make cast");
  915.         printnode(np);
  916.     }
  917.     return np;
  918. }
  919.  
  920. is_ty_start()
  921. {
  922.     NODEP rv;
  923.  
  924.     if (is_tykw(cur->e_token))
  925.         return 1;
  926.     if (cur->e_token == ID) {
  927.         rv = allsyms(cur);
  928.         if (rv && rv->e_sc == K_TYPEDEF)
  929.             return 1;
  930.     }
  931.     return 0;
  932. }
  933.  
  934. /* assemble decl and put in listpp */
  935. new_sym(listpp, xp)
  936. NODEP *listpp;
  937. NODEP xp;
  938. {
  939.     NODEP old;
  940.  
  941.     if (xp == NULL)
  942.         return 0;
  943. /* put in table */
  944.     if (debug) {
  945.         printf("New sym sc %c", "EARTSCH"[xp->e_sc-K_EXTERN]);
  946.         printnode(xp);
  947.     }
  948.     /* later look for previous definition */
  949.     if (listpp == (NODE **)symtab) {
  950.         old = hlook(listpp, xp);
  951.         if (old == NULL || def2nd(old, xp))
  952.             puthlist(listpp, xp);
  953.     } else {
  954.         old = llook(*listpp, xp);
  955.         if (old == NULL || def2nd(old, xp))
  956.             putlist(listpp, xp);
  957.     }
  958.     return 1;
  959. }
  960.  
  961. /* look for storage class */
  962. d_scl(defau)
  963. {
  964.     int rv;
  965.  
  966.     if (is_sclass(cur->e_token)) {
  967.         rv = cur->e_token;
  968.         fadvnode();
  969.         return rv;
  970.     }
  971.     /* no storage class specified */
  972.     return defau;
  973. }
  974.  
  975. NODEP
  976. d_declr(head, forcast)
  977. NODEP head;
  978. {
  979.     NODEP e1;
  980.     NODEP declarator(), rev_decl();
  981.     NODEP xp, tailp;
  982.  
  983.     e1 = declarator();
  984.     xp = rev_decl(e1, &tailp, forcast);
  985.     if (xp) {
  986.         tailp->n_tptr = head;
  987.         tailp->n_flags |= N_COPYT;
  988.         return xp;
  989.     } else if (forcast)
  990.         return head;
  991.     else
  992.         return NULL;
  993. }
  994.  
  995. NODEP
  996. rev_decl(np,tailpp,forcast)
  997. NODEP np, *tailpp;
  998. {
  999.     NODEP rv, scan, nxt;
  1000.  
  1001.     rv = NULL;
  1002.     for (scan = np; scan != NULL; scan = nxt) {
  1003.         nxt = scan->n_next;
  1004.         scan->n_next = NULL;
  1005.         if (rv == NULL) {
  1006.             *tailpp = scan;
  1007.             scan->n_tptr = NULL;
  1008.             rv = scan;
  1009.         } else {
  1010.             scan->n_tptr = rv;
  1011.             rv = scan;
  1012.         }
  1013.         e_to_t(rv);
  1014.         switch (rv->t_token) {
  1015.         case UNARY '*':
  1016.             sprintf(rv->n_name, "Ptr to");
  1017.             break;
  1018.         case '(':
  1019.             sprintf(rv->n_name, "Fun ret");
  1020.             break;
  1021.         case '[':
  1022.             sprintf(rv->n_name, "Ary of");
  1023.             break;
  1024.         case ID:
  1025.             break;
  1026.         default:
  1027.             error("bad type xpr");
  1028.             return NULL;
  1029.         }
  1030.     }
  1031.     /* if normal decl and see something, must see id first */
  1032.     if (!ok_revx(rv,forcast))
  1033.         rv = NULL;
  1034.     return rv;
  1035. }
  1036.  
  1037. /*
  1038.  * Looking for type part of a decl
  1039.  */
  1040. NODEP
  1041. d_type()
  1042. {
  1043.     int btype, adj;
  1044.     NODEP rv;
  1045.     NODEP bas_type(), decl_su(), decl_enum();
  1046.  
  1047.     /* look for 'struct', 'union', 'enum' or typedef ID */
  1048.     switch (cur->e_token) {
  1049.     case ID:
  1050.         rv = allsyms(cur);
  1051.         if (rv && rv->e_sc == K_TYPEDEF) {
  1052.             fadvnode();
  1053.             rv = rv->n_tptr;
  1054.             return rv;
  1055.         }
  1056.         return NULL;
  1057.     case K_STRUCT:
  1058.         return decl_su(0);
  1059.     case K_UNION:
  1060.         return decl_su(1);
  1061.     case K_ENUM:
  1062.         return decl_enum();
  1063.     }
  1064.  
  1065.     /* look for modifiers 'long', 'short', 'unsigned' */
  1066.     adj = 0;
  1067.     while (is_tadj(cur->e_token)) {
  1068.         switch (cur->e_token) {
  1069.         case K_SHORT:
  1070.             adj |= SAW_SHORT;
  1071.             break;
  1072.         case K_LONG:
  1073.             adj |= SAW_LONG;
  1074.             break;
  1075.         case K_UNSIGNED:
  1076.             adj |= SAW_UNS;
  1077.             break;
  1078.         }
  1079.         fadvnode();
  1080.     }
  1081.  
  1082.     /* look for base type 'char', 'int', 'float', 'double', 'void'*/
  1083.     if (is_btype(cur->e_token)) {
  1084.         btype = cur->e_token;
  1085.         fadvnode();
  1086.     } else if (adj == 0)    /* saw nothing */
  1087.         return NULL;
  1088.     else
  1089.         btype = K_INT;
  1090.  
  1091.     if (adj)
  1092.         btype = adj_type(btype, adj);
  1093.     rv = bas_type(btype);
  1094.     return rv;
  1095. }
  1096.  
  1097. NODEP
  1098. decl_enum()
  1099. {
  1100.     NODEP bas_type();
  1101.  
  1102.     fadvnode();     /* skip 'enum' */
  1103.  
  1104.     if (cur->e_token == ID) {       /* ignore tag */
  1105.         fadvnode();
  1106.     }
  1107.     if (cur->e_token == '{') {      /* new declaration */
  1108.         fadvnode();     /* skip '{' */
  1109.         en_decls();     /* global scope */
  1110.         if (cur->e_token != '}')
  1111.             error("expect }");
  1112.         else
  1113.             fadvnode();     /* skip '}' */
  1114.     }
  1115.     return bas_type(K_INT);
  1116. }
  1117.  
  1118. extern lineno;
  1119.  
  1120. NODEP
  1121. decl_su(isunion)
  1122. {
  1123.     register NODEP rv, tagp;
  1124.     NODEP *attab;
  1125.  
  1126.     fadvnode();     /* skip 'struct' or 'union' */
  1127.  
  1128.     attab = level ? &blktab->b_tags : &tagtab;
  1129.     tagp = NULL;
  1130.     if (cur->e_token == ID) {       /* hold on to ID node */
  1131.         tagp = cur;
  1132.         e_to_t(tagp);
  1133.         advnode();
  1134.         nnmadd(tagp, isunion ? ".U" : ".S");
  1135.     }
  1136.     if (cur->e_token == '{') {      /* new declaration */
  1137.         if (tagp == NULL) {     /* make fake name */
  1138.             tagp = allocnode();
  1139.             sprintf(tagp->n_name, isunion ? "%dU" :
  1140.                     "%dS", lineno);
  1141.         }
  1142.         fadvnode();     /* skip '{' */
  1143.         if (rv = llook(*attab, tagp)) {
  1144.             freenode(tagp);
  1145.             if (rv->n_right) {
  1146.                 errors("struct redefined", rv->n_name);
  1147.                 freenode(rv->n_right);
  1148.                 rv->n_right = NULL;
  1149.             }
  1150.         } else {        /* new defn */
  1151.             rv = tagp;
  1152.             rv->t_token = isunion ? K_UNION : K_STRUCT;
  1153.             rv->n_flags |= N_BRKPR; /* break print loops */
  1154.             putlist(attab, rv);
  1155.         }
  1156.         su_decls(&rv->n_right, isunion,
  1157.                 &rv->t_size, &rv->t_aln);
  1158.         if (cur->e_token != '}')
  1159.             error("expect }");
  1160.         else
  1161.             fadvnode();     /* skip '}' */
  1162.     } else {        /* reference to old */
  1163.         if (tagp == NULL) {
  1164.             error("nonsense struct");
  1165.             goto out;
  1166.         }
  1167.         /* ANSI special decl
  1168.             struct <tag> ;
  1169.            for hiding old tag within block */
  1170.         if (cur->e_token == ';' && level)
  1171.             rv = llook(*attab, tagp);
  1172.         else
  1173.             rv = alltags(tagp);
  1174.         if (rv == NULL) {       /* delayed tag */
  1175.             rv = tagp;
  1176.             rv->t_token = isunion ? K_UNION : K_STRUCT;
  1177.             rv->n_flags |= N_BRKPR; /* break print loops */
  1178.             putlist(attab, rv);
  1179.             goto out;
  1180.         } else
  1181.             freenode(tagp);
  1182.     }
  1183. out:
  1184.     return rv;
  1185. }
  1186.  
  1187. NODE *
  1188. alltags(np)
  1189. NODE *np;
  1190. {
  1191.     register NODE *bp;
  1192.     NODE *rv;
  1193.  
  1194.     for (bp=blktab; bp != NULL; bp = bp->n_next)
  1195.         if ((rv = llook(bp->b_tags, np)) != NULL)
  1196.             return rv;
  1197.     return llook(tagtab, np);
  1198. }
  1199.  
  1200. NODE *
  1201. allsyms(np)
  1202. NODE *np;
  1203. {
  1204.     register NODE *bp;
  1205.     NODE *rv;
  1206.  
  1207.     for (bp=blktab; bp != NULL; bp = bp->n_next)
  1208.         if ((rv = llook(bp->b_syms, np)) != NULL)
  1209.             return rv;
  1210.     return hlook(symtab, np);
  1211. }
  1212.  
  1213. sim_type(a,b)
  1214. register NODE *a, *b;
  1215. {
  1216. more:
  1217.     if (a == b)
  1218.         return 1;
  1219.     if (a == NULL || b == NULL)
  1220.         return 0;
  1221.     if (a->t_token != b->t_token)
  1222.         return 0;
  1223.     if (a->t_size != b->t_size && a->t_size && b->t_size)
  1224.         return 0;
  1225.     a = a->n_tptr;
  1226.     b = b->n_tptr;
  1227.     goto more;
  1228. }
  1229.  
  1230. /* 2nd def of same name at same level */
  1231. /* OK if one extern and types the same */
  1232. def2nd(old,new)
  1233. NODEP old, new;
  1234. {
  1235.     int osc, nsc;
  1236.  
  1237.     if (sim_type(old->n_tptr, new->n_tptr) == 0)
  1238.         goto bad;
  1239.     osc = old->e_sc;
  1240.     nsc = new->e_sc;
  1241.     if (nsc == K_EXTERN) {  /* works only if no further use allowed */
  1242.         freenode(new);
  1243.         return 0;
  1244.     }
  1245.     if (osc == K_EXTERN) {
  1246.         /* replace old def with new one */
  1247.         /* for now, just put new one on list too */
  1248.         return 1;
  1249.     }
  1250. bad:
  1251.     errorn("bad 2nd decl of ", new);
  1252.     /* use 2nd def so other stuff works */
  1253.     return 1;
  1254. }
  1255.  
  1256. /* saw fun but no body */
  1257. fix_fun(np)
  1258. NODE *np;
  1259. {
  1260.     if (np == NULL) return;
  1261.     if (np->n_tptr->t_token == '(') {       /* fix to extern */
  1262.         if (np->e_sc != K_TYPEDEF)
  1263.             np->e_sc = K_EXTERN;
  1264.     }
  1265. }
  1266.  
  1267. e_to_t(np)
  1268. NODE *np;
  1269. {
  1270.     int token;
  1271.  
  1272.     token = np->e_token;
  1273.     np->t_token = token;
  1274.     np->t_size = 0;
  1275.     np->t_aln = 0;
  1276. }
  1277. SHAR_EOF
  1278. cat << \SHAR_EOF > expr.c
  1279. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  1280.  *
  1281.  * Permission is granted to anyone to use this software for any purpose
  1282.  * on any computer system, and to redistribute it freely, with the
  1283.  * following restrictions:
  1284.  * 1) No charge may be made other than reasonable charges for reproduction.
  1285.  * 2) Modified versions must be clearly marked as such.
  1286.  * 3) The authors are not responsible for any harmful consequences
  1287.  *    of using this software, even if they result from defects in it.
  1288.  *
  1289.  *    expr.c
  1290.  *
  1291.  *    Expression parse routines
  1292.  *
  1293.  *    All routines return either NULL or a valid tree
  1294.  *        binop nodes have non-null left and right
  1295.  *        unop nodes have non-null left
  1296.  *
  1297.  *    Special nodes:
  1298.  *        '(' : function call.  left:name-expr right:args 
  1299.  *        ',': if part of function arg list, ival:num. descendants
  1300.  *        '?' : ?switch.  left:test-expr right:':' part
  1301.  *          ':' : left:true-expr right:false-expr
  1302.  *        TCONV: left:convertee tptr:type-list
  1303.  *        TSIZEOF: tptr:type-list
  1304.  *
  1305.  */
  1306.  
  1307. #include <stdio.h>
  1308. #include "param.h"
  1309. #include "nodes.h"
  1310. #include "tok.h"
  1311.  
  1312. extern NODEP cur;
  1313. NODEP getnode();
  1314. NODEP opt_follow();
  1315.  
  1316. extern int oflags[];
  1317. #define debug oflags['x'-'a']
  1318.  
  1319. advnode()
  1320. {
  1321.     cur = getnode();
  1322. }
  1323.  
  1324. fadvnode()
  1325. {
  1326.     freenode(cur);
  1327.     cur = getnode();
  1328. }
  1329.  
  1330. NODEP
  1331. gete_or_ty()
  1332. {
  1333.     NODEP getexpr(), makecast();
  1334.     NODEP rv;
  1335.  
  1336.     if (is_ty_start()) {
  1337.         rv = makecast();
  1338.         if (debug) {
  1339.             printf("TY_X");
  1340.             printnode(rv);
  1341.         }
  1342.         return rv;
  1343.     } else
  1344.         return getexpr();
  1345. }
  1346.  
  1347. /* call this for any expr including comma's */
  1348. NODEP
  1349. getexpr()
  1350. {
  1351.     NODEP np, get_f_expr();
  1352.  
  1353.     np = get_f_expr(0);
  1354.     return np;
  1355. }
  1356.  
  1357. NODEP
  1358. get_f_expr(flg)
  1359. int flg;
  1360. {
  1361.     NODEP assignx();
  1362.     register NODEP op, lpart, rpart;
  1363.     int i = 0;
  1364.  
  1365.     lpart = assignx();
  1366.     if (lpart == NULL) {
  1367.         return NULL;
  1368.     }
  1369.     i++;
  1370. more:
  1371.     if (cur->e_token != ',')
  1372.         return lpart;
  1373.  
  1374.     op = cur;  advnode();
  1375.     rpart = assignx();
  1376.     if (rpart == NULL) {
  1377.         error("',' expr syntax");
  1378.         return lpart;
  1379.     }
  1380.     i++;
  1381.     op->n_left = lpart;
  1382.     op->n_right = rpart;
  1383.     op->e_type = E_BIN;
  1384.     op->e_ival = flg ? i : 0;
  1385.     lpart = op;
  1386.     if (debug) {
  1387.         printf("COMMA");
  1388.         printnode(op);
  1389.     }
  1390.     goto more;
  1391. }
  1392.  
  1393. /* call this if you want expr w/o comma's */
  1394. NODEP
  1395. assignx()
  1396. {
  1397.     NODEP questx();
  1398.     register NODEP op, lpart, rpart;
  1399.  
  1400.     lpart = questx();
  1401.     if (lpart == NULL)
  1402.         return NULL;
  1403.     if (!isassign(cur->e_token) && cur->e_token != '=')
  1404.         return lpart;
  1405.     op = cur;  advnode();
  1406.     rpart = assignx();
  1407.     if (rpart == NULL) {
  1408.         error("'=op' expr syntax");
  1409.         return lpart;
  1410.     }
  1411.     op->n_left = lpart;
  1412.     op->n_right = rpart;
  1413.     op->e_type = E_BIN;
  1414.     if (debug) {
  1415.         printf("ASSIGN");
  1416.         printnode(op);
  1417.     }
  1418.     return op;
  1419. }
  1420.  
  1421. /* call this if you want expr w/o assign's or comma's */
  1422. /* i.e. constant-expression */
  1423. NODEP
  1424. questx()
  1425. {
  1426.     NODEP binary();
  1427.     register NODEP holdq, holdc;
  1428.     NODEP qpart, tpart, fpart;
  1429.  
  1430.     qpart = binary();
  1431.     if (qpart == NULL)
  1432.         return NULL;
  1433.     if (cur->e_token != '?')
  1434.         return qpart;
  1435.     holdq = cur;  advnode();
  1436.     tpart = questx();
  1437.     if (tpart == NULL || cur->e_token != ':') {
  1438. bad:
  1439.         error("'?:' expr syntax");
  1440.         return qpart;
  1441.     }
  1442.     holdc = cur;  advnode();
  1443.     fpart = questx();
  1444.     if (fpart == NULL) goto bad;
  1445.     holdc->n_left = tpart;
  1446.     holdc->n_right = fpart;
  1447.     holdc->e_type = E_BIN;
  1448.     holdq->n_left = qpart;
  1449.     holdq->n_right = holdc;
  1450.     holdq->e_type = E_BIN;
  1451.     if (debug) {
  1452.         printf("QUEST");
  1453.         printnode(holdq);
  1454.     }
  1455.     return holdq;
  1456. }
  1457.  
  1458. NODEP
  1459. binary()
  1460. {
  1461.     NODEP unary(), buildbin();
  1462.     register NODEP rv, op, e2;
  1463.  
  1464.     rv = unary();
  1465.     if (rv == NULL)
  1466.         return NULL;
  1467.     rv->e_prec = 0;
  1468. more:
  1469.     if (cur->e_prec == 0)    /* not binary op */
  1470.         return rv;
  1471.     op = cur;  advnode();
  1472.     e2 = unary();
  1473.     if (e2 == NULL) {
  1474.         error("bin-op expr syntax");
  1475.         return rv;
  1476.     }
  1477.     e2->e_prec = 0;
  1478.     rv = buildbin(rv, op, e2);
  1479.     if (debug) {
  1480.         printf("BINARY");
  1481.         printnode(rv);
  1482.     }
  1483.     goto more;
  1484. }
  1485.  
  1486. NODEP
  1487. buildbin(lpart, op, upart)
  1488. NODEP lpart, op, upart;
  1489. {
  1490.     register NODEP look, tail;
  1491.     NODEP rv;
  1492.  
  1493.     tail = NULL;
  1494.     look = lpart;
  1495.     for (look=lpart; op->e_prec < look->e_prec; look=look->n_right)
  1496.         tail = look;
  1497.     if (tail == NULL) {
  1498.         op->n_left = lpart;
  1499.         op->n_right = upart;
  1500.         rv = op;
  1501.     } else {
  1502.         tail->n_right = op;
  1503.         op->n_left = look;
  1504.         op->n_right = upart;
  1505.         rv = lpart;
  1506.     }
  1507.     op->e_type = E_BIN;
  1508.     return rv;
  1509. }
  1510.  
  1511. NODEP
  1512. unary()
  1513. {
  1514.     register NODEP tp,e1;
  1515.     NODEP primary();
  1516.  
  1517.     if (cur->e_flags & CAN_U) {
  1518.         tp = cur;  advnode();
  1519.         if (tp->e_prec) {  /* also have BINARY op */
  1520.             tp->e_token = UNARY tp->e_token;
  1521.             strcat(tp->n_name, "U");
  1522.         }
  1523.         tp->n_left = unary();
  1524.         tp->e_type = E_UNARY;
  1525.         goto check;
  1526.     } else
  1527.     switch (cur->e_token) {
  1528.     case '(':
  1529.         fadvnode();
  1530.         tp = gete_or_ty();
  1531.         if (cur->e_token != ')') {
  1532.             error("missing )");
  1533.         } else
  1534.             fadvnode();
  1535.         if (tp == NULL)
  1536.             return NULL;
  1537.         if (tp->e_token == TCONV && tp->n_left == NULL) {
  1538.             sprintf(tp->n_name, "cast to");
  1539.             tp->n_left = unary();
  1540.             tp->e_type = E_UNARY;
  1541.         } else {
  1542.             tp = opt_follow(tp);
  1543.             goto out;
  1544.         }
  1545.         goto check;
  1546.     case K_SIZEOF:
  1547.         tp = cur;
  1548.         advnode();
  1549.         if (cur->e_token == '(') { /* may be type expr */
  1550.             fadvnode();
  1551.             e1 = gete_or_ty();
  1552.             if (cur->e_token != ')') {
  1553.                 error("missing )");
  1554.             } else
  1555.                 fadvnode();
  1556.         } else
  1557.             e1 = unary();
  1558.         if (e1 == NULL) {
  1559.             error("sizeof expr syntax");
  1560.             return NULL;
  1561.         }
  1562.         if (e1->e_token == TCONV) {
  1563.             freeunit(tp);
  1564.             e1->e_token = TSIZEOF;
  1565.             sprintf(e1->n_name, "T-sizeof");
  1566.             tp = e1;
  1567.             tp->e_type = E_LEAF;
  1568.             goto out;
  1569.         } else {
  1570.             tp->e_type = E_UNARY;
  1571.             tp->n_left = e1;
  1572.         }
  1573.         goto check;
  1574.     default:
  1575.         tp = primary();
  1576.         goto out;
  1577.     }
  1578. check:
  1579.     if (tp == NULL) return NULL;
  1580.     if (tp->n_left == NULL) {
  1581.         error("u-op expr syntax");
  1582.         return NULL;
  1583.     }
  1584. out:
  1585.     if (debug) {
  1586.         printf("UNARY");
  1587.         printnode(tp);
  1588.     }
  1589.     return tp;
  1590. }
  1591.  
  1592. NODEP
  1593. primary()
  1594. {
  1595.     register NODEP e1;
  1596.  
  1597.     switch (cur->e_token) {
  1598.     case ID:
  1599.     case ICON:
  1600.     case FCON:
  1601.     case SCON:
  1602.         e1 = cur;
  1603.         e1->e_type = E_LEAF;
  1604.         advnode();
  1605.         break;
  1606.     case '(':
  1607.         fadvnode();
  1608.         e1 = getexpr();
  1609.         if (cur->e_token != ')')
  1610.             error("missing )");
  1611.         else
  1612.             fadvnode();
  1613.         break;
  1614.     default:
  1615.         e1 = NULL;
  1616.     }
  1617.     if (e1 == NULL)
  1618.         return NULL;
  1619.     return opt_follow(e1);
  1620. }
  1621.  
  1622. NODEP
  1623. opt_follow(np)
  1624. NODEP np;
  1625. {
  1626.     register NODEP tp, e1, t2;
  1627.  
  1628.     switch (cur->e_token) {
  1629.     case '[':
  1630.         tp = cur;  advnode();
  1631.         e1 = getexpr();
  1632.         if (cur->e_token != ']') {
  1633.             error("missing ]");
  1634.             return np;
  1635.         } else {
  1636.             t2 = cur;  advnode();
  1637.         }
  1638.         if (e1 == NULL) {
  1639.             error("empty []");
  1640.             return np;
  1641.         }
  1642.         t2->n_left = np;
  1643.         t2->n_right = e1;
  1644.         t2->e_type = E_BIN;
  1645.         t2->e_token = '+';
  1646.         strcpy(t2->n_name, "+ [");
  1647.  
  1648.         tp->n_left = t2;
  1649.         tp->e_type = E_UNARY;
  1650.         tp->e_token = STAR;
  1651.         strcpy(tp->n_name, "U*");
  1652.  
  1653.         goto out;
  1654.     case '(':
  1655.         tp = cur;
  1656.         advnode();
  1657.         e1 = get_f_expr(1);
  1658.         if (cur->e_token != ')')
  1659.             error("expect )");
  1660.         else
  1661.             fadvnode();
  1662.         tp->n_left = np;
  1663.         tp->n_right = e1;
  1664.         tp->e_type = E_SPEC;
  1665.         goto out;
  1666.     case '.':
  1667.     case ARROW:
  1668.         tp = cur;  advnode();
  1669.         if (cur->e_token != ID) {
  1670.             error("expect ID");
  1671.             return np;
  1672.         }
  1673.         tp->n_left = np;
  1674.         tp->n_right = cur;
  1675.         tp->e_type = E_SPEC;
  1676.         if (tp->e_token == ARROW) { /* make into (*X).Y */
  1677.             tp->e_token = '.';
  1678.             strcpy(tp->n_name, ".");
  1679.  
  1680.             t2 = allocnode();
  1681.             t2->e_token = STAR;
  1682.             t2->n_left = np;
  1683.             t2->e_type = E_UNARY;
  1684.             strcpy(t2->n_name, "U*");
  1685.  
  1686.             tp->n_left = t2;    
  1687.         }
  1688.         advnode();
  1689.         goto out;
  1690.     case DOUBLE '+':
  1691.     case DOUBLE '-':
  1692.         tp = cur;  advnode();
  1693.         tp->e_token = (tp->e_token == DOUBLE '+') ? POSTINC : POSTDEC;
  1694.         strcat(tp->n_name, "post");
  1695.         tp->n_left = np;
  1696.         tp->e_type = E_UNARY;
  1697.         goto out;
  1698.     default:
  1699.         return np;
  1700.     }
  1701. out:
  1702.     return opt_follow(tp);
  1703. }
  1704.  
  1705. /* restricted version of unary for declarations or coertions */
  1706. /* allows NULL primary part */
  1707. NODEP
  1708. declarator()
  1709. {
  1710.     register NODEP tp,e1;
  1711.     NODEP ty_primary(), ty_follow();
  1712.  
  1713.     if (cur->e_token == '*') {
  1714.         tp = cur;
  1715.         tp->e_token = UNARY tp->e_token;
  1716.         strcat(tp->n_name, "U");
  1717.         advnode();
  1718.         tp->n_left = declarator();
  1719.         return tp;
  1720.     } else
  1721.     switch (cur->e_token) {
  1722.     case '(':
  1723.         tp = cur;
  1724.         advnode();
  1725.         e1 = declarator();
  1726.         if (cur->e_token != ')') {
  1727.             error("expect )");
  1728.         } else
  1729.             fadvnode();
  1730.         if (e1 == NULL) {    /* special "fun of" */
  1731.             /* left and right already NULL */
  1732.             return ty_follow(tp);
  1733.         } else {
  1734.             freeunit(tp);
  1735.             return ty_follow(e1);
  1736.         }
  1737.     default:
  1738.         return ty_primary();
  1739.     }
  1740. }
  1741.  
  1742. /* restricted version of primary for "declarator" */
  1743. NODEP
  1744. ty_primary()
  1745. {
  1746.     register NODEP e1;
  1747.     NODEP ty_follow();
  1748.  
  1749.     switch (cur->e_token) {
  1750.     case ID:
  1751.         e1 = cur;
  1752.         advnode();
  1753.         break;
  1754.     case '(':
  1755.         fadvnode();
  1756.         e1 = declarator();
  1757.         if (cur->e_token != ')')
  1758.             error("expect )");
  1759.         else
  1760.             fadvnode();
  1761.         break;
  1762.     default:
  1763.         e1 = NULL;
  1764.     }
  1765.     return ty_follow(e1);
  1766. }
  1767.  
  1768. /* restricted version of opt_follow for 'declarator' */
  1769. /* allow null [] */
  1770. NODEP
  1771. ty_follow(np)
  1772. NODEP np;
  1773. {
  1774.     register NODEP tp, e1;
  1775.     NODEP ty_args();
  1776.  
  1777.     switch (cur->e_token) {
  1778.     case '[':
  1779.         tp = cur;
  1780.         advnode();
  1781.         e1 = questx();
  1782.         if (cur->e_token != ']')
  1783.             error("expect ]");
  1784.         else
  1785.             fadvnode();
  1786.         tp->n_left = np;
  1787.         tp->n_right = e1;
  1788.         goto out;
  1789.     case '(':
  1790.         tp = cur;
  1791.         advnode();
  1792.         e1 = ty_args();    /* allow args of fun to follow */
  1793.         if (cur->e_token != ')')
  1794.             error("expect )");
  1795.         else
  1796.             fadvnode();
  1797.         tp->n_left = np;
  1798.         tp->n_right = e1;
  1799.         goto out;
  1800.     default:
  1801.         return np;
  1802.     }
  1803. out:
  1804.     return ty_follow(tp);
  1805. }
  1806.  
  1807. /* called for args of function declaration or NULL */
  1808. NODEP
  1809. ty_args()
  1810. {
  1811.     NODEP opt_id();
  1812.     register NODEP rv, tail, new;
  1813.  
  1814.     rv = opt_id();
  1815.     if (rv == NULL)
  1816.         return NULL;
  1817.     tail = rv;
  1818. more:
  1819.     if (cur->e_token != ',')
  1820.         return rv;
  1821.     fadvnode();
  1822.     new = opt_id();
  1823.     if (new == NULL) {
  1824.         error("expect as-op value");
  1825.         return rv;
  1826.     }
  1827.     tail->n_left = new;
  1828.     tail = new;
  1829.     goto more;
  1830. }
  1831.  
  1832. NODEP
  1833. opt_id()
  1834. {
  1835.     NODEP rv;
  1836.  
  1837.     if (cur->e_token == ID) {
  1838.         rv = cur;
  1839.         advnode();
  1840.         return rv;
  1841.     } else
  1842.         return NULL;
  1843. }
  1844. SHAR_EOF
  1845. cat << \SHAR_EOF > fix.c
  1846. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  1847.  *
  1848.  * Permission is granted to anyone to use this software for any purpose
  1849.  * on any computer system, and to redistribute it freely, with the
  1850.  * following restrictions:
  1851.  * 1) No charge may be made other than reasonable charges for reproduction.
  1852.  * 2) Modified versions must be clearly marked as such.
  1853.  * 3) The authors are not responsible for any harmful consequences
  1854.  *    of using this software, even if they result from defects in it.
  1855.  *
  1856.  *    fix.c
  1857.  *
  1858.  *    Motorola has is not consistent in what operations allow
  1859.  *    which operands.  This section compensates for that --
  1860.  *    tries to find the best way to do something.
  1861.  */
  1862.  
  1863. #include <stdio.h>
  1864. #include "param.h"
  1865. #include "nodes.h"
  1866. #include "flags.h"
  1867. #include "bstok.h"
  1868. #include "gen.h"
  1869. #include "ops.h"
  1870.  
  1871. #define FAIL 0
  1872. #define OKAY 1
  1873.  
  1874. #define CL_IMM    IOPD
  1875. #define CL_AREG    AOPD
  1876. #define CL_DREG DOPD
  1877. #define CL_ADR    MOPD
  1878.  
  1879. #define RETAREG    0x100
  1880. #define RETDREG 0x200
  1881. #define RETLEFT    0x400
  1882. #define RETRIGHT 0x800
  1883.  
  1884. #define LISTMP    1
  1885. #define RISTMP    2
  1886. #define NDASSOC    4
  1887. #define CANRL    8
  1888. #define CANLR    0x10
  1889. #define CANRD    0x20
  1890. #define CANDL    0x40
  1891. #define CANLD    0x80
  1892. #define CANDD    0x100
  1893. #define CANDR    0x200
  1894.  
  1895. struct mtbl {
  1896.     int restr;
  1897.     char *code;
  1898.     int needregs;
  1899. } tbl2[] = {
  1900.     {LISTMP|CANRL,
  1901.         "\tN.S\t>A,<A\n", RETLEFT},
  1902.     {RISTMP|CANLR|NDASSOC,
  1903.         "\tN.S\t<A,>A\n", RETRIGHT},
  1904.     {CANRD,
  1905.         "\tmove.S\t<A,A\n\tN.S\t>A,A\n", RETDREG},
  1906.     {CANLD|NDASSOC,
  1907.         "\tmove.S\t>A,A\n\tN.S\t<A,A\n", RETDREG},
  1908.     /* only EOR and shifts get to here */
  1909.     {CANDL|LISTMP,
  1910.         "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETLEFT|1},
  1911.     {CANDR|RISTMP|NDASSOC,
  1912.         "\tmove.S\t<A,R1\n\tN.S\tR1,A\n", RETRIGHT|1},
  1913.     {CANDD,
  1914.         "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n",
  1915.             RETDREG|1},
  1916.     {0}
  1917. };
  1918.  
  1919. struct mtbl tblmul[] = {
  1920.     {CANRL|LISTMP,
  1921.         "\tmulU\t>A,<A\n", RETLEFT},
  1922.     {CANLR|RISTMP,
  1923.         "\tmulU\t<A,>A\n", RETRIGHT},
  1924.     {CANRD,
  1925.         "\tmove.w\t>A,A\n\tmulU\t<A,A\n", RETDREG},
  1926.     {0}
  1927. };
  1928.  
  1929. struct mtbl tbldiv[] = {
  1930.     {CANRL|LISTMP,
  1931.         "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
  1932.     {CANRD,
  1933.         "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n", RETDREG},
  1934.     {0}
  1935. };
  1936.  
  1937. struct mtbl tbludiv[] = {
  1938.     {CANRD,
  1939.         "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n", RETDREG},
  1940.     {0}
  1941. };
  1942.  
  1943. struct mtbl tblc[] = {
  1944.     {CANRL,
  1945.         "\tcmp.<S\t>A,<A\n", 0},
  1946.     {CANRD,
  1947.         "\tmove.<S\t<A,R1\n\tcmp.<S\t>A,R1\n", 1},
  1948. /* shouldnt get to here! */
  1949.     {CANDL,
  1950.         "\tmove.<S\t>A,R1\n\tcmp.<S\tR1,<A\n", 1},
  1951.     {CANDD,
  1952.         "\tmove.<S\t>A,R1\n\tmove.<S\t<A,R2\n\tcmp.<S\tR1,R2\n", 2},
  1953.     {0}
  1954. };
  1955.  
  1956. struct mtbl tblas[] = {
  1957.     {CANRL,
  1958.         "\tN.S\t>A,<A\n", RETLEFT},
  1959.     {CANDL,
  1960.         "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", 1|RETLEFT},
  1961.     /* only MUL, DIV and shifts should get to here */
  1962.     {CANRD,
  1963.         "\tmove.S\t<A,A\n\tN.S\t>A,A\n\tmove.S\tA,<A\n",
  1964.             RETDREG},
  1965.     {CANLD|NDASSOC,
  1966.         "\tmove.S\t>A,A\n\tN.S\t<A,A\n\tmove.S\tA,<A\n",
  1967.             RETDREG},
  1968.     {CANDD,
  1969.     "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n\tmove.S\tA,<A\n",
  1970.             RETDREG|1},
  1971.     {0}
  1972. };
  1973.  
  1974. struct mtbl tblamul[] = {
  1975.     {CANRL,
  1976.         "\tmulU\t>A,<A\n", RETLEFT},
  1977.     {CANLR|RISTMP,
  1978.         "\tmulU\t<A,>A\n\tmove.w\t>A,<A\n", RETRIGHT},
  1979.     {CANRD,
  1980.         "\tmove.w\t<A,A\n\tmulU\t>A,A\n\tmove.w\tA,<A\n", RETDREG},
  1981.     {0}
  1982. };
  1983.  
  1984. struct mtbl tbladiv[] = {
  1985.     {CANRL,
  1986.         "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
  1987.     {CANRD,
  1988.     "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tmove.w\tA,<A\n",
  1989.         RETDREG},
  1990.     {0}
  1991. };
  1992.  
  1993. struct mtbl tbluadiv[] = {
  1994.     {CANRD,
  1995.     "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tmove.w\tA,<A\n",
  1996.         RETDREG},
  1997.     {0}
  1998. };
  1999.  
  2000. struct mtbl tblamod[] = {
  2001.     {CANRL,
  2002.         "\text.l\t<A\n\tdivs\t>A,<A\n\tswap\t<A\n", RETLEFT},
  2003.     {CANRD,
  2004.   "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
  2005.         RETDREG},
  2006.     {0}
  2007. };
  2008.  
  2009. struct mtbl tbluamod[] = {
  2010.     {CANRD,
  2011.   "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
  2012.         RETDREG},
  2013.     {0}
  2014. };
  2015.  
  2016. class(np)
  2017. NODEP np;
  2018. {
  2019.     switch (np->g_token) {
  2020.     case ICON:
  2021.         return CL_IMM;
  2022.     case ONAME:
  2023.         return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
  2024.     case OREG:
  2025.         return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
  2026.     case PUSHER:
  2027.         return CL_ADR;
  2028.     case REGVAR:
  2029.         if (np->g_rno < AREG)
  2030.             return CL_DREG;
  2031.         else
  2032.             return CL_AREG;
  2033.     default:
  2034.         printf("Weird class ");
  2035.         return CL_IMM;
  2036.     }
  2037. }
  2038.  
  2039. int canswap;
  2040. NODEP matchnp;
  2041.  
  2042. fix_cmp(np, flags)
  2043. NODEP np;
  2044. {
  2045.     NODEP rp = np->n_right;
  2046.  
  2047.     /* special stuff for ICON 0 */
  2048.     if (rp->g_token == ICON && rp->g_offs == 0 &&
  2049.         (rp->g_flags & IMMEDID)) {
  2050.         addcode(np, "<Q");
  2051.         return OKAY;
  2052.     }
  2053.     canswap = 0;
  2054.     return fix_sub(np, flags, tblc);
  2055. }
  2056.  
  2057. fix2ops(np, flags)
  2058. NODEP np;
  2059. {
  2060.     canswap = flags & ASSOC;
  2061.     return fix_sub(np, flags, tbl2);
  2062. }
  2063.  
  2064. fixmul(np, flags)
  2065. NODEP np;
  2066. {
  2067.     return fix_sub(np, flags, tblmul);
  2068. }
  2069.  
  2070. fixdiv(np, flags)
  2071. NODEP np;
  2072. {
  2073.     return fix_sub(np, flags, np->g_ty == ET_U ? tbludiv : tbldiv);
  2074. }
  2075.  
  2076. fixmod(np, flags)
  2077. NODEP np;
  2078. {
  2079.     int r;
  2080.  
  2081.     r = fixdiv(np, flags);
  2082.     addcode(np, "\tswap\tA\n");
  2083.     return r;
  2084. }
  2085.  
  2086. fixamul(np, flags)
  2087. NODEP np;
  2088. {
  2089.     return fix_sub(np, flags, tblamul);
  2090. }
  2091.  
  2092. fixadiv(np, flags)
  2093. NODEP np;
  2094. {
  2095.     return fix_sub(np, flags, np->g_ty == ET_U ? tbluadiv : tbladiv);
  2096. }
  2097.  
  2098. fixamod(np, flags)
  2099. NODEP np;
  2100. {
  2101.     return fix_sub(np, flags, np->g_ty == ET_U ? tbluamod : tblamod);
  2102. }
  2103.  
  2104. fix_asn(np, flags)
  2105. NODEP np;
  2106. {
  2107.     canswap = 0;
  2108.     return fix_sub(np, flags, tblas);
  2109. }
  2110.  
  2111. fix_sub(np, flags, tbl)
  2112. register NODEP np;
  2113. struct mtbl *tbl;
  2114. {
  2115.     NODEP lp = np->n_left, rp = np->n_right;
  2116.     int lclass, rclass;
  2117.     register struct mtbl *p;
  2118.     int rv;
  2119.  
  2120.     lclass = class(lp);
  2121.     rclass = class(rp);
  2122.     matchnp = np;
  2123.  
  2124.     for (p = tbl; p->restr; p++)
  2125.         if ((rv = cando(flags, p->restr, lclass, rclass))) {
  2126.             dotbl(p, np);
  2127.             return OKAY;
  2128.         }
  2129.     printf("no code table match! ");
  2130.     return FAIL;
  2131. }
  2132.  
  2133. dotbl(p, np)
  2134. struct mtbl *p;
  2135. NODEP np;
  2136. {
  2137.     register int i, k;
  2138.  
  2139.     if (p->needregs) {
  2140.         i = p->needregs;
  2141.         if (i & RETLEFT)
  2142.             inherit(np);
  2143.         else if (i & RETRIGHT)
  2144.             rinherit(np);
  2145.         else if (i & RETAREG)
  2146.             retreg(np, ralloc(AREG));
  2147.         else if (i & RETDREG)
  2148.             retreg(np, ralloc(0));
  2149.         k = i & 7;
  2150.         while (k--)
  2151.             tempr(np, 0);
  2152.         k = (i/AREG) & 7;
  2153.         while (k--)
  2154.             tempr(np, AREG);
  2155.     }
  2156.     addcode(np, p->code);
  2157. }
  2158.  
  2159. #define canflag(l,r)    (l << cansh[r])
  2160.  
  2161. short cansh[] = {0, 0, 4, 0, 8, 0, 0, 0, 12};
  2162.  
  2163. cando(flags, restr, lc, rc)
  2164. register restr;
  2165. {
  2166.     NODEP lp = matchnp->n_left, rp = matchnp->n_right;
  2167.  
  2168.     if (restr & RISTMP) {
  2169.         if ((rc & (CL_DREG|CL_AREG)) == 0 ||
  2170.             istemp(rp->g_rno) == 0)
  2171.             return 0;
  2172.     } else if (restr & LISTMP) {
  2173.         if ((lc & (CL_DREG|CL_AREG)) == 0 ||
  2174.             istemp(lp->g_rno) == 0)
  2175.             return 0;
  2176.     }
  2177.     if (restr & NDASSOC) {
  2178.         if (canswap == 0)
  2179.             return 0;
  2180.     }
  2181.     if (restr & (CANLR|CANLD)) {
  2182.         flags |= quickflag(lp, flags);
  2183.     } else if (restr & (CANRL|CANRD)) {
  2184.         flags |= quickflag(rp, flags);
  2185.     }
  2186.     flags &= 0xfff;
  2187.     if (restr & CANLR) {
  2188.         if ((flags & canflag(lc,rc)) == 0)
  2189.             return 0;
  2190.     } else if (restr & CANRL) {
  2191.         if ((flags & canflag(rc,lc)) == 0)
  2192.             return 0;
  2193.     } else if (restr & CANRD) {
  2194.         if ((flags & canflag(rc,CL_DREG)) == 0)
  2195.             return 0;
  2196.     } else if (restr & CANDL) {
  2197.         if ((flags & canflag(CL_DREG,lc)) == 0)
  2198.             return 0;
  2199.     } else if (restr & CANLD) {
  2200.         if ((flags & canflag(lc,CL_DREG)) == 0)
  2201.             return 0;
  2202.     } else if (restr & CANDR) {
  2203.         if ((flags & canflag(CL_DREG,rc)) == 0)
  2204.             return 0;
  2205.     } else if (restr & CANDD) {
  2206.         if ((flags & DOPD) == 0)
  2207.             return 0;
  2208.     }
  2209.     return 1;
  2210. }
  2211.  
  2212. quickflag(np, flags)
  2213. NODEP np;
  2214. {
  2215.     long offs;
  2216.  
  2217.     if (np->g_token != ICON)
  2218.         return 0;
  2219.     offs = np->g_offs;
  2220.     if ((flags & QOPD) && np->g_offs >= 1 && np->g_offs <= 8)
  2221.         return IOPD;
  2222.     if ((flags & ONEOPM) && np->g_offs == 1)
  2223.         return IOPM;
  2224.     return 0;
  2225. }
  2226.  
  2227. /*
  2228.  * stuff to do field extract and field assign
  2229.  * Yes, this stuff can be optimized a lot more ... feel free
  2230.  */
  2231. fldget(np, flags)
  2232. register NODEP np;
  2233. {
  2234.     int how;
  2235.  
  2236.     how = 1;
  2237.     if (np->g_fldo == 0)
  2238.         how = 0;    /* no shift needed */
  2239.     else if (np->g_fldo > 8)
  2240.         how = 2;    /* shift too big for immediate */
  2241.  
  2242.     np->n_left->g_offs += np->g_offs;    /* major HACK, hope it works */
  2243.  
  2244.     retreg(np, ralloc(0));
  2245.  
  2246.     addcode(np, "\tmove\t<A,A\n");        /* get word */
  2247.     if (how)                /* shift to position */
  2248.         addcode(np, how==1 ?    "\tlsr\t#Y,A\n" :
  2249.             "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
  2250.     addcode(np, "\tand\t#W,A\n");        /* mask off top */
  2251.  
  2252.     return OKAY;
  2253. }
  2254.  
  2255. fldasn(np, flags)
  2256. register NODEP np;
  2257. {
  2258.     int how;
  2259.  
  2260.     how = 1;
  2261.     if (np->g_fldo == 0)
  2262.         how = 0;    /* no shift needed */
  2263.     else if (np->g_fldo > 8)
  2264.         how = 2;    /* shift too big for immediate */
  2265.  
  2266.     retreg(np, ralloc(0));
  2267.  
  2268.     tempr(np, 0);
  2269.  
  2270.     addcode(np, "\tmove\t>A,A\n");        /* value */
  2271.     if (needmask(np))        /* mask off high bits */
  2272.         addcode(np, "\tand\t#W,A\n");
  2273.     if (how)    /* shift into position */
  2274.         addcode(np, how==1 ?    "\tlsl\t#Y,A\n" :
  2275.                     "\tlsl\t#8,A\n\tlsl\t#Z,A\n");
  2276.  
  2277.     addcode(np, "\tmove\t<A,R1\n");        /* old value */
  2278.     addcode(np, "\tand\t#X,R1\n");        /* mask out old value */
  2279.     addcode(np, "\tor\tA,R1\n");        /* set new field */
  2280.     addcode(np, "\tmove\tR1,<A\n");        /* store new word */
  2281.  
  2282.     if (how && (flags & NOVAL_OK) == 0)    /* return value */
  2283.         addcode(np, how==1 ?    "\tlsr\t#Y,A\n" :
  2284.                     "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
  2285.  
  2286.     return OKAY;
  2287. }
  2288.  
  2289. needmask(np)
  2290. register NODEP np;
  2291. {
  2292.     NODEP lp = np->n_left;
  2293.  
  2294.     if (np->g_fldw + np->g_fldo >= 16)
  2295.         return 0;
  2296.  
  2297.     if (lp->g_token != ICON)
  2298.         return 1;
  2299.     if ((int)lp->g_offs & ~ones(np->g_fldw)) {
  2300.         warn("value too big for field");
  2301.         return 1;
  2302.     }
  2303.     return 0;
  2304. }
  2305. SHAR_EOF
  2306. cat << \SHAR_EOF > fun.c
  2307. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2308.  *
  2309.  * Permission is granted to anyone to use this software for any purpose
  2310.  * on any computer system, and to redistribute it freely, with the
  2311.  * following restrictions:
  2312.  * 1) No charge may be made other than reasonable charges for reproduction.
  2313.  * 2) Modified versions must be clearly marked as such.
  2314.  * 3) The authors are not responsible for any harmful consequences
  2315.  *    of using this software, even if they result from defects in it.
  2316.  *
  2317.  *    fun.c
  2318.  *
  2319.  *    Handle function entry, exit, etc.
  2320.  *    Parse statements.
  2321.  *    Also, general syntax error recovery strategy.
  2322.  */
  2323.  
  2324. #include <stdio.h>
  2325. #include "param.h"
  2326. #include "tok.h"
  2327. #include "nodes.h"
  2328. #include "cookie.h"
  2329.  
  2330. #if MMCC
  2331. overlay "pass2"
  2332. #endif
  2333.  
  2334. extern NODE *cur;
  2335.  
  2336. int level;
  2337. NODE *blktab;
  2338. NODE *labels;
  2339.  
  2340. struct swittbl {
  2341.     NODEP    caselist;
  2342.     int    deflbl;
  2343. } *curswit;
  2344.  
  2345. int curbrk, curcont;
  2346. int funtopl, funbotl, funretl, funstrl;
  2347. NODEP funtyp;
  2348. int maxregs;
  2349. long maxlocs;
  2350.  
  2351. int skipon;
  2352.  
  2353. NODEP glb_decls();
  2354.  
  2355. extern int oflags[];
  2356. #define debugl oflags['l'-'a']
  2357. #define debugs oflags['s'-'a']
  2358. #define debugv oflags['v'-'a']
  2359.  
  2360. findtok(x)
  2361. {
  2362.     while (cur->e_token != EOFTOK && cur->e_token != x)
  2363.         fadvnode();
  2364.     if (cur->e_token == EOFTOK)
  2365.         exit(1);
  2366. }
  2367.  
  2368. extern NODEP symtab[];
  2369.  
  2370. program()
  2371. {
  2372.     NODEP last;
  2373.  
  2374.     skipon = 0;
  2375. more:
  2376.     last = glb_decls();
  2377.     if (cur->e_token == EOFTOK)
  2378.         return;
  2379.     if (last) skipon = 0;   /* saw something valid */
  2380.     if (last && last->n_tptr && last->n_tptr->t_token == '(') {
  2381.     /* possible function definition */
  2382.         if (debugs) {
  2383.             printf("FUN ");
  2384.             put_nnm(last);
  2385.         }
  2386.         out_fstart(last);
  2387.         last->e_sc = K_EXTERN;
  2388.         fun_start(last->n_tptr);
  2389.         args_blk(last->n_tptr->n_right);
  2390.         sub_block();
  2391.         fun_end();
  2392.         clr_lvl(); /* for args block */
  2393.         goto more;
  2394.     }
  2395.     /* error if get to here */
  2396.     if (last) {
  2397.         error("missing ;");
  2398.         goto more;
  2399.     } else {
  2400.         skip();
  2401.         goto more;
  2402.     }
  2403. }
  2404.  
  2405. fun_start(np)
  2406. NODEP np;
  2407. {
  2408.     NODEP functy();
  2409.  
  2410.     funtyp = functy(np);
  2411.     curbrk = curcont = -1;
  2412.     funtopl = new_lbl();
  2413.     funbotl = new_lbl();
  2414.     funretl = new_lbl();
  2415.     switch (funtyp->t_token) {
  2416.     case K_STRUCT:
  2417.     case K_UNION:
  2418.         funstrl = new_lbl();
  2419.         break;
  2420.     default:
  2421.         funstrl = 0;
  2422.     }
  2423.     maxregs = 0;
  2424.     maxlocs = 0;
  2425.     out_br(funbotl);
  2426.     def_lbl(funtopl);
  2427. }
  2428.  
  2429. fun_end()
  2430. {
  2431.     NODEP np;
  2432.  
  2433.     if (labels) {
  2434.         for (np = labels; np; np = np->n_next)
  2435.             if (np->c_defined == 0)
  2436.                 errorn("undefined label", np);
  2437.         freenode(labels);
  2438.         labels = NULL;
  2439.     }
  2440.     def_lbl(funretl);
  2441.     out_fret(maxregs, funstrl);
  2442.     def_lbl(funbotl);
  2443.     out_fend(maxregs, maxlocs);
  2444.     out_br(funtopl);
  2445.     if (funstrl)
  2446.         out_fs(funstrl, funtyp->t_size);
  2447. }
  2448.  
  2449. skip()
  2450. {
  2451.     if (skipon == 0) {
  2452.         error("syntax (try skipping...)");
  2453.         skipon = 1;
  2454.     }
  2455.     fadvnode();
  2456. }
  2457.  
  2458. block()
  2459. {
  2460.     int some;
  2461.     int sawsome;
  2462.  
  2463.     some = loc_decls();
  2464.     if (cur->e_token == EOFTOK)
  2465.         return;
  2466.     if (some) skipon = 0;
  2467. more:
  2468.     sawsome = stmts();
  2469.     if (sawsome) skipon = 0;
  2470.     if (cur->e_token == '}') {
  2471.         if (blktab->b_regs > maxregs)
  2472.             maxregs = blktab->b_regs;
  2473.         if (blktab->b_size + blktab->b_tsize > maxlocs)
  2474.             maxlocs = blktab->b_size + blktab->b_tsize;
  2475.         return;
  2476.     }
  2477.  
  2478.     /* error if get to here */
  2479.     if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
  2480.         /* get out of block */
  2481.         return;
  2482.     else {
  2483.         skip();
  2484.         goto more;
  2485.     }
  2486. }
  2487.  
  2488. clr_lvl()
  2489. {
  2490.     NODE *bp;
  2491.  
  2492.     level--;
  2493.     bp = blktab;
  2494.     blktab = bp->n_next;
  2495.     bp->n_next = NULL;
  2496.     if (debugl && bp->b_syms) {
  2497.         printf("local syms %d", level);
  2498.         printlist(bp->b_syms);
  2499.     }
  2500.     freenode(bp->b_syms);
  2501.     if (debugl && bp->b_tags) {
  2502.         printf("local tags %d", level);
  2503.         printlist(bp->b_tags);
  2504.     }
  2505.     freenode(bp->b_tags);
  2506.     freenode(bp);
  2507. }
  2508.  
  2509. eat(c)
  2510. {
  2511.     char *p = "assume X";
  2512.  
  2513.     if (cur->e_token == c)
  2514.         fadvnode();
  2515.     else {
  2516.         p[strlen(p) - 1] = c;
  2517.         error(p);
  2518.     }
  2519. }
  2520.  
  2521. sub_block()
  2522. {
  2523.     register NODE *new;
  2524.  
  2525.     if (debugs)
  2526.         printf("{ ");
  2527.     eat('{');
  2528.     level++;
  2529.     new = allocnode();
  2530.     new->n_next = blktab;
  2531.     sprintf(new->n_name, "sub{");
  2532.     blktab = new;
  2533.     block();
  2534.     clr_lvl();
  2535.     eat('}');
  2536.     if (debugs)
  2537.         printf("}\n");
  2538. }
  2539.  
  2540. args_blk(np)
  2541. NODEP np;
  2542. {
  2543.     register NODE *p;
  2544.     register NODE *new;
  2545.     NODE *tp;
  2546.     NODEP llook();
  2547.     long size;
  2548.     int rmask;
  2549.  
  2550.     size = 0;
  2551.     rmask = 0;
  2552.     new = allocnode();
  2553.     new->n_next = blktab;
  2554.     sprintf(new->n_name, "arg{");
  2555.     blktab = new;
  2556.     level++;
  2557.     loc_decls();
  2558.     /* make sure all decls were in arg list */
  2559.     for (p=new->b_syms; p != NULL; p = p->n_next)
  2560.         if (llook(np, p) == NULL)
  2561.             errorn("ID not param", p);
  2562.     /* now make any names not mentioned INT */
  2563.     /* and generate offsets and alloc regs */
  2564.     for (p=np; p != NULL; p = p->n_next) {
  2565.         if ((tp=llook(new->b_syms, p)) == NULL) {
  2566.             def_arg(&new->b_syms, p);
  2567.             tp = new->b_syms;
  2568.         }
  2569.         lc_size(&size, &rmask, tp);
  2570.         if (tp->e_sc == K_REGISTER)
  2571.             reg_arg(&rmask, tp);
  2572.         if (debugv) {
  2573.             printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
  2574.             put_nnm(tp);
  2575.             putchar('\n');
  2576.         }
  2577.     }
  2578.     new->b_regs = rmask;
  2579. }
  2580.  
  2581. reg_arg(rp, xp)
  2582. int *rp;
  2583. NODEP xp;
  2584. {
  2585.     if (lc_reg(rp, xp) == 0) {      /* out of regs? */
  2586.         xp->e_sc = K_AUTO;
  2587.         return;
  2588.     }
  2589.     out_argreg(xp);
  2590. }
  2591.  
  2592.  
  2593. stmts()
  2594. {
  2595.     int didsome;
  2596.  
  2597.     didsome = 0;
  2598.     while (stmt())
  2599.         didsome++;
  2600.     return didsome;
  2601. }
  2602.  
  2603. stmt_bc(brk,cont)
  2604. {
  2605.     int svb, svc;
  2606.  
  2607.     svb = curbrk;
  2608.     svc = curcont;
  2609.     curbrk = brk;
  2610.     curcont = cont;
  2611.  
  2612.     stmt();
  2613.  
  2614.     curbrk = svb;
  2615.     curcont = svc;
  2616. }
  2617.  
  2618. stmt_b(brk)
  2619. {
  2620.     int svb;
  2621.  
  2622.     svb = curbrk;
  2623.     curbrk = brk;
  2624.  
  2625.     stmt();
  2626.  
  2627.     curbrk = svb;
  2628. }
  2629.  
  2630. /* do a single statement */
  2631. stmt()
  2632. {
  2633.     register tok;
  2634.     NODEP np;
  2635.     NODEP getexpr();
  2636.     int i;
  2637.  
  2638. more:
  2639.     tok = cur->e_token;
  2640.     if (is_stkw(tok)) {
  2641.         if (is_blkst(tok)) {
  2642.             i = blk_stmt();
  2643.         } else if (is_brast(tok)) {
  2644.             i = bra_stmt();
  2645.         } else if (is_lblst(tok)) {
  2646.             i = lbl_stmt();
  2647.         } else
  2648.             i = asm_stmt();
  2649.         if (i == 0)
  2650.             goto more;
  2651.         return 1;
  2652.     }
  2653.     else if (tok == '{') {
  2654.         sub_block();
  2655.         return 1;
  2656.     } else if (tok == ';') {
  2657.         fadvnode();
  2658.         return 1;
  2659.     }
  2660.     np = getexpr();
  2661.     if (np) {
  2662.         if (cur->e_token == ':') {
  2663.             fadvnode();
  2664.             label(np);
  2665.             goto more;
  2666.         }
  2667.         expr_stmt(np);
  2668.         if (cur->e_token != ';')
  2669.             error("missing ;");
  2670.         else
  2671.             fadvnode();
  2672.         return 1;
  2673.     }
  2674.     return 0;
  2675. }
  2676.  
  2677. expr_stmt(np)
  2678. NODEP np;
  2679. {
  2680.     if (debugs) {
  2681.         printf("E_STMT ");
  2682.         if (debugs > 1)
  2683.             printnode(np);
  2684.     }
  2685.     do_expr(np, FORSIDE);
  2686. }
  2687.  
  2688. label(np)
  2689. NODEP np;
  2690. {
  2691.     register NODEP tp;
  2692.     NODEP llook();
  2693.  
  2694.     if (debugs) {
  2695.         printf("LABEL ");
  2696.         if (debugs > 1)
  2697.             printnode(np);
  2698.     }
  2699.     if (np->e_token != ID) {
  2700.         error("weird label");
  2701.         return;
  2702.     }
  2703.     tp = llook(labels, np);
  2704.     if (tp) {
  2705.         freenode(np);
  2706.         if (tp->c_defined) {
  2707.             error("duplicate label");
  2708.             return;
  2709.         }
  2710.     } else {
  2711.         putlist(&labels, np);
  2712.         tp = np;
  2713.         tp->c_casel = new_lbl();
  2714.     }
  2715.     tp->c_defined = 1;
  2716.     def_lbl(tp->c_casel);
  2717. }
  2718.  
  2719.  
  2720. extern int lineno;
  2721.  
  2722. blk_stmt()
  2723. {
  2724.     register tok;
  2725.     int l1, l2, l3;
  2726.     NODEP e1, e2, e3;
  2727.     NODEP opt_expr(), paren_expr(), def_type();
  2728.     struct swittbl locswit, *oldp;
  2729.     int svline, svline2;
  2730.  
  2731.     tok = cur->e_token;
  2732.     fadvnode();
  2733.     switch (tok) {
  2734.     case K_IF:
  2735.         if (debugs)
  2736.             printf("IF ");
  2737.         l1 = new_lbl();
  2738.         e1 = paren_expr();
  2739.         gen_brf(e1, l1);
  2740.         eat(')');
  2741.         stmt();
  2742.         opt_else(l1);
  2743.         return 1;
  2744.     case K_WHILE:
  2745.         if (debugs)
  2746.             printf("WHILE ");
  2747.         e1 = paren_expr();
  2748.         l1 = new_lbl();
  2749.         l2 = new_lbl();
  2750.  
  2751.         def_lbl(l1);
  2752.         gen_brf(e1,l2);
  2753.         eat(')');
  2754.  
  2755.         stmt_bc(l2,l1);
  2756.  
  2757.         out_br(l1);
  2758.         def_lbl(l2);
  2759.         return 1;
  2760.     case K_DO:
  2761.         if (debugs)
  2762.             printf("DO ");
  2763.         l1 = new_lbl();
  2764.         l2 = new_lbl();
  2765.         l3 = new_lbl();
  2766.         def_lbl(l1);
  2767.  
  2768.         stmt_bc(l3,l2);
  2769.  
  2770.         def_lbl(l2);
  2771.         eat(K_WHILE);
  2772.         e1 = paren_expr();
  2773.         gen_brt(e1, l1);
  2774.         eat(')');
  2775.         eat(';');
  2776.         def_lbl(l3);
  2777.         return 1;
  2778.     case K_FOR:
  2779.         if (debugs)
  2780.             printf("FOR ");
  2781.         l1 = new_lbl();
  2782.         l2 = new_lbl();
  2783.         l3 = new_lbl();
  2784.         eat('(');
  2785.         e1 = opt_expr();
  2786.         expr_stmt(e1);
  2787.         eat(';');
  2788.         def_lbl(l1);
  2789.         e2 = opt_expr();
  2790.         if (e2)
  2791.             gen_brf(e2,l3);
  2792.         eat(';');
  2793.         e3 = opt_expr();        /* save for later */
  2794.         svline = lineno;
  2795.         eat(')');
  2796.  
  2797.         stmt_bc(l3,l2);
  2798.  
  2799.         def_lbl(l2);
  2800.  
  2801.         svline2 = lineno;
  2802.         lineno = svline;
  2803.         expr_stmt(e3);
  2804.         lineno = svline2;
  2805.  
  2806.         out_br(l1);
  2807.         def_lbl(l3);
  2808.         return 1;
  2809.     case K_SWITCH:
  2810.         if (debugs)
  2811.             printf("SWITCH ");
  2812.         e1 = paren_expr();
  2813.         l1 = new_lbl();
  2814.         l2 = new_lbl();
  2815.         to_d0(e1, def_type());
  2816.         eat(')');
  2817.  
  2818.         out_br(l2);
  2819.         oldp = curswit;
  2820.         curswit = &locswit;
  2821.         locswit.caselist = NULL;
  2822.         locswit.deflbl = -1;
  2823.  
  2824.         stmt_b(l1);
  2825.  
  2826.         out_br(l1);
  2827.         def_lbl(l2);
  2828.         gen_switch(locswit.caselist, locswit.deflbl);
  2829.         curswit = oldp;
  2830.         def_lbl(l1);
  2831.         return 1;
  2832.     case K_ELSE:
  2833.         error("unexpected 'else'");
  2834.         fadvnode();
  2835.         return 0;
  2836.     }
  2837. }
  2838.  
  2839. NODEP
  2840. paren_expr()
  2841. {
  2842.     NODEP np;
  2843.     NODEP need_expr();
  2844.  
  2845.     eat('(');
  2846.     np = need_expr();
  2847.     return np;
  2848. }
  2849.  
  2850. bra_stmt()
  2851. {
  2852.     register tok;
  2853.     NODEP np, tp;
  2854.     NODEP opt_expr(), llook();
  2855.  
  2856.     tok = cur->e_token;
  2857.     fadvnode();
  2858.     switch (tok) {
  2859.     case K_BREAK:
  2860.         if (debugs)
  2861.             printf("BRK");
  2862.         eat(';');
  2863.         out_br(curbrk);
  2864.         return 1;
  2865.     case K_CONTINUE:
  2866.         if (debugs)
  2867.             printf("CONT ");
  2868.         eat(';');
  2869.         out_br(curcont);
  2870.         return 1;
  2871.     case K_RETURN:
  2872.         if (debugs)
  2873.             printf("RETURN ");
  2874.         np = opt_expr();
  2875.         if (np) {
  2876.             if (funstrl)
  2877.                 ret_stru(np);
  2878.             else
  2879.                 to_d0(np, funtyp);
  2880.         }
  2881.         out_br(funretl);
  2882.         eat(';');
  2883.         return 1;
  2884.     case K_GOTO:
  2885.         if (debugs)
  2886.             printf("GOTO ");
  2887.         np = cur;  advnode();
  2888.         if (np->e_token != ID)
  2889.             error("bad goto");
  2890.         else {
  2891.             tp = llook(labels, np);
  2892.             if (tp) {
  2893.                 freenode(np);
  2894.             } else {
  2895.                 tp = np;
  2896.                 putlist(&labels, tp);
  2897.                 tp->c_casel = new_lbl();
  2898.             }
  2899.             out_br(tp->c_casel);
  2900.         }
  2901.         eat(';');
  2902.         return 1;
  2903.     }
  2904. }
  2905.  
  2906. lbl_stmt()
  2907. {
  2908.     register tok;
  2909.     NODEP need_expr(), np;
  2910.     int l1, i;
  2911.  
  2912.     l1 = new_lbl();
  2913.     tok = cur->e_token;
  2914. again:
  2915.     fadvnode();
  2916.     switch (tok) {
  2917.     case K_CASE:
  2918.         if (debugs)
  2919.             printf("CASE ");
  2920.         np = need_expr();
  2921.         i = conxval(np);
  2922.         add_case(i,l1);
  2923.         eat(':');
  2924.         break;
  2925.     case K_DEFAULT:
  2926.         if (debugs)
  2927.             printf("DEFAULT ");
  2928.         if (curswit->deflbl >= 0)
  2929.             error("multiple 'default'");
  2930.         curswit->deflbl = l1;
  2931.         eat(':');
  2932.     }
  2933.     tok = cur->e_token;    /* lookahead for more cases */
  2934.     if (tok == K_CASE || tok == K_DEFAULT)
  2935.         goto again;
  2936.     def_lbl(l1);
  2937.     return 0;
  2938. }
  2939.  
  2940. asm_stmt()
  2941. {
  2942.     NODEP np, getexpr();
  2943.  
  2944.     fadvnode();
  2945.     np = getexpr();
  2946.     if (np == NULL || np->e_token != SCON) {
  2947.         error("bad asm() func");
  2948.     } else {
  2949.         out_asm(np);
  2950.         freenode(np);
  2951.     }
  2952.     eat(';');
  2953. }
  2954.  
  2955. NODEP
  2956. opt_expr()
  2957. {
  2958.     NODE *np, *getexpr();
  2959.  
  2960.     np = getexpr();
  2961.     if (np) {
  2962.         if (debugs) {
  2963.             printf("OXPR ");
  2964.             if (debugs > 1)
  2965.                 printnode(np);
  2966.         }
  2967.     }
  2968.     return np;
  2969. }
  2970.  
  2971. NODEP
  2972. need_expr()
  2973. {
  2974.     NODE *np, *getexpr();
  2975.  
  2976.     np = getexpr();
  2977.     if (np) {
  2978.         if (debugs) {
  2979.             printf("NXPR ");
  2980.             if (debugs > 1)
  2981.                 printnode(np);
  2982.         }
  2983.     } else
  2984.         error("need expr");
  2985.     return np;
  2986. }
  2987.  
  2988. opt_else(l1)
  2989. {
  2990.     int l2;
  2991.  
  2992.     if (cur->e_token == K_ELSE) {
  2993.         if (debugs)
  2994.             printf("ELSE ");
  2995.         fadvnode();
  2996.         l2 = new_lbl();
  2997.         out_br(l2);
  2998.         def_lbl(l1);
  2999.         stmt();
  3000.         def_lbl(l2);
  3001.     } else
  3002.         def_lbl(l1);
  3003. }
  3004.  
  3005. add_case(val, lbl)
  3006. {
  3007.     NODEP np, last, p;
  3008.  
  3009.     np = allocnode();
  3010.     np->c_casev = val;
  3011.     np->c_casel = lbl;
  3012.     sprintf(np->n_name, "%d:%d", val, lbl);
  3013.  
  3014.     last = NULL;
  3015.     for (p = curswit->caselist; p; last=p, p=p->n_next)
  3016.         if (p->c_casev == val) {
  3017.             error("duplicate case");
  3018.             return;
  3019.         } else if (p->c_casev > val)
  3020.             break;
  3021.     if (last) {
  3022.         last->n_next = np;
  3023.         np->n_next = p;
  3024.     } else {
  3025.         curswit->caselist = np;
  3026.         np->n_next = p;
  3027.     }
  3028.     if (debugs) {
  3029.         printf("CASELIST\n");
  3030.         printnode(curswit->caselist);
  3031.     }
  3032. }
  3033.  
  3034. to_d0(np, typ)
  3035. NODEP np, typ;
  3036. {
  3037.     NODEP tp;
  3038.  
  3039.     tp = allocnode();
  3040.     tp->e_token = TCONV;
  3041.     tp->n_tptr = typ;
  3042.     tp->n_flags |= N_COPYT;
  3043.     tp->n_left = np;
  3044.     tp->e_type = E_UNARY;
  3045.     strcpy(tp->n_name, "r cast");
  3046.  
  3047.     do_expr(tp, IND0);
  3048. }
  3049.  
  3050. ret_stru(np)
  3051. NODEP np;
  3052. {
  3053.     p2_expr(&np);
  3054.     if (same_type(np->n_tptr, funtyp) == 0) {
  3055.         error("bad struct return type");
  3056.         return;
  3057.     }
  3058.     genx(np, RETSTRU);
  3059. }
  3060. SHAR_EOF
  3061. cat << \SHAR_EOF > g2.c
  3062. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  3063.  *
  3064.  * Permission is granted to anyone to use this software for any purpose
  3065.  * on any computer system, and to redistribute it freely, with the
  3066.  * following restrictions:
  3067.  * 1) No charge may be made other than reasonable charges for reproduction.
  3068.  * 2) Modified versions must be clearly marked as such.
  3069.  * 3) The authors are not responsible for any harmful consequences
  3070.  *    of using this software, even if they result from defects in it.
  3071.  *
  3072.  *    g2.c
  3073.  *
  3074.  *    Generate code for binary nodes.
  3075.  */
  3076.  
  3077. #include <stdio.h>
  3078. #include "param.h"
  3079. #include "nodes.h"
  3080. #include "flags.h"
  3081. #include "bstok.h"
  3082. #include "gen.h"
  3083. #include "ops.h"
  3084.  
  3085. #define FAIL    0
  3086. #define OKAY    1
  3087.  
  3088. extern int cookflags[];
  3089.  
  3090. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  3091. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  3092.  
  3093. struct bop {
  3094.     char *s_op, *u_op;
  3095.     int opflags;
  3096. } bops[] = {
  3097.     {"muls",        "mulu", EOPD |ASSOC},
  3098.     {"divs",        "divu", EOPD},
  3099.     {"divs",        "divu", EOPD},
  3100.     {"and",         "and",  EOPD|DOPE|IOPE |ASSOC},
  3101.     {"or",          "or",   EOPD|DOPE|IOPE |ASSOC},
  3102.     {"eor",         "eor",  DOPE|IOPE |ASSOC},
  3103.     {"add",         "add",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
  3104.     {"sub",         "sub",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
  3105.     {"asl",         "lsl",  DOPD|QOPD|ONEOPM},
  3106.     {"asr",         "lsr",  DOPD|QOPD|ONEOPM},
  3107. };
  3108.  
  3109. char *tstnm[] = {
  3110.     "lt",           /* < */
  3111.     "gt",           /* > */
  3112.     "le",           /* <= */
  3113.     "ge",           /* >= */
  3114.     "eq",           /* == */
  3115.     "ne",           /* != */
  3116. };
  3117.  
  3118. int tstx[] = {
  3119.     B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
  3120. };
  3121.  
  3122. char *utstnm[] = {
  3123.     "cs",           /* < */
  3124.     "hi",           /* > */
  3125.     "ls",           /* <= */
  3126.     "cc",           /* >= */
  3127.     "eq",           /* == */
  3128.     "ne",           /* != */
  3129. };
  3130.  
  3131. int utstx[] = {
  3132.     B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
  3133. };
  3134.  
  3135. b_eval(np, cookie)
  3136. register NODEP np;
  3137. {
  3138.     NODEP lp = np->n_left, rp = np->n_right;
  3139.     NODEP tp;
  3140.     int lcook = FORADR, rcook = FORADR;
  3141.  
  3142.     switch (np->g_token) {          /* special cookies */
  3143.     case DOUBLE '&':
  3144.     case DOUBLE '|':
  3145.         lcook = rcook = FORCC;
  3146.         break;
  3147.     case '?':
  3148.         lcook = FORCC;
  3149.         break;
  3150.     case '(':
  3151.         rcook = FORPUSH;
  3152.         break;
  3153.     case ',':
  3154.         if (np->g_offs) /* function args */
  3155.             lcook = rcook = FORPUSH;
  3156.         else {
  3157.             lcook = FORSIDE;
  3158.             rcook = cookie;
  3159.         }
  3160.         break;
  3161.     case '=':
  3162.         rcook = FORIMA;
  3163.         break;
  3164.     case '+':
  3165.     case '-':
  3166.         tp = rp;
  3167.         while (tp->g_token == TCONV && tp->g_ty != ET_F)
  3168.             tp = tp->n_left;
  3169.         if (tp->g_token == ICON)
  3170.             lcook = FORIMA;
  3171.         break;
  3172.     }
  3173.  
  3174.     if (np->g_type == EV_LR) {
  3175.         if (eval(lp,lcook) == FAIL)
  3176.             return FAIL;
  3177.         freetmps(lp);
  3178.         if (eval(rp,rcook) == FAIL)
  3179.             return FAIL;
  3180.         freetmps(rp);
  3181.     } else if (np->g_type == EV_RL) {
  3182.         if (eval(rp,rcook) == FAIL)
  3183.             return FAIL;
  3184.         freetmps(rp);
  3185.         if (eval(lp,lcook) == FAIL)
  3186.             return FAIL;
  3187.         freetmps(lp);
  3188.     } else {    /* EV_LRSEP */
  3189.         if (eval(lp,lcook) == FAIL)
  3190.             return FAIL;
  3191.         freetmps(lp);
  3192.         free1(NULL, lp);
  3193.         if (eval(rp,rcook) == FAIL)
  3194.             return FAIL;
  3195.         freetmps(rp);
  3196.     }
  3197.     return b_sube(np, cookflags[cookie]);
  3198. }
  3199.  
  3200. b_sube(np, flags)
  3201. register NODEP np;
  3202. {
  3203.     NODEP lp = np->n_left, rp = np->n_right;
  3204.     register int i, r;
  3205.     int argsize;
  3206.     char buf[40];
  3207.  
  3208.     if (isassign(np->g_token))
  3209.         return as_eval(np);
  3210.  
  3211.     switch (np->g_token) {
  3212.     case '=':
  3213.         if (specasn(np, flags) || strasn(np))
  3214.             return OKAY;
  3215.         inherit(np);
  3216.         addcode(np, "\tmove.S\t>A,<A\n");
  3217.         return OKAY;
  3218.  
  3219.     case '(':
  3220.         argsize = argmod(rp);
  3221.         free1(NULL,rp);
  3222.         if (np->g_ty == ET_A) {         /* struct returned */
  3223.             frc_ral(AREG);
  3224.             indir(np, AREG);
  3225.         } else {
  3226.             frc_ral(0);
  3227.             retreg(np, 0);
  3228.         }
  3229.          externfuncref(np);
  3230.         sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
  3231.         addcode(np, buf);
  3232.         return OKAY;
  3233.  
  3234.     case ',':
  3235.         if (np->g_offs == 0)    /* normal ',' */
  3236.             rinherit(np);
  3237.         return OKAY;
  3238.  
  3239.     case DOUBLE '&':
  3240.         free1(NULL, rp);
  3241.         r = ralloc(0);
  3242.         retreg(np, r);
  3243.         holdlbls(np);
  3244.         np->g_betw = iscc(lp) ? "<FL1\n" :
  3245.             "<Q\tbeq\tL1\n";
  3246.         addcode(np, iscc(rp) ? ">FL1\n" :
  3247.             ">Q\tbeq\tL1\n");
  3248.         addcode(np, "\tmoveq\t#1,A\n");
  3249.         addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
  3250.         return OKAY;
  3251.  
  3252.     case DOUBLE '|':
  3253.         free1(NULL, rp);
  3254.         r = ralloc(0);
  3255.         retreg(np, r);
  3256.         holdlbls(np);
  3257.         np->g_betw = iscc(lp) ? "<TL1\n" :
  3258.             "<Q\tbne\tL1\n";
  3259.         addcode(np, iscc(rp) ? ">TL1\n" :
  3260.             ">Q\tbne\tL1\n");
  3261.         addcode(np, "\tclr\tA\n");
  3262.         addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
  3263.         return OKAY;
  3264.  
  3265.     case '?':
  3266.         rinherit(np);
  3267.         rinhlbls(np);
  3268.         np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
  3269.         return OKAY;
  3270.  
  3271.     case ':':
  3272.         free1(NULL, rp);
  3273.         r = ralloc(0);
  3274.         retreg(np, r);
  3275.         holdlbls(np);
  3276.         np->g_betw = same_a(np, lp) ?
  3277.             "\tbra\tL2\nL1:\n"  :
  3278.             "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
  3279.         if (!same_a(np, rp))
  3280.             addcode(np, "\tmove.S\t>A,A\n");
  3281.         addcode(np, "L2:\n");
  3282.         return OKAY;
  3283.  
  3284.     case '<':
  3285.         i = 0;    goto dotst;
  3286.     case '>':
  3287.         i = 1;    goto dotst;
  3288.     case LTEQ:
  3289.         i = 2;    goto dotst;
  3290.     case GTEQ:
  3291.         i = 3;    goto dotst;
  3292.     case DOUBLE '=':
  3293.         i = 4;    goto dotst;
  3294.     case NOTEQ:
  3295.         i = 5;
  3296. dotst:
  3297.         fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
  3298.         if (flags & CC_OK) {
  3299.             np->g_token = (lp->g_ty == ET_U ?
  3300.             utstx[i] : tstx[i]) + BR_TOK;
  3301.         } else {
  3302.             strcpy(np->n_name, lp->g_ty == ET_U ?
  3303.             utstnm[i] : tstnm[i]);
  3304.             r = ralloc(0);
  3305.             retreg(np, r);
  3306.             addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  3307.         }
  3308.         return OKAY;
  3309.  
  3310.     case '*':
  3311.         return fixmul(np, bops[0].opflags);
  3312.     case '/':
  3313.         return fixdiv(np, bops[1].opflags);
  3314.     case '%':
  3315.         return fixmod(np, bops[2].opflags);
  3316.     case '&':       i = 3;  goto doop;
  3317.     case '|':       i = 4;  goto doop;
  3318.     case '^':       i = 5;  goto doop;
  3319.     case '+':
  3320.         if (optadd(np, flags, 1))
  3321.             return OKAY;
  3322.             i = 6;    goto doop;
  3323.     case '-':
  3324.         if (optadd(np, flags, -1))
  3325.             return OKAY;
  3326.             i = 7;    goto doop;
  3327.     case DOUBLE '<':i = 8;  goto doop;
  3328.     case DOUBLE '>':i = 9;
  3329. doop:
  3330.         strcpy(np->n_name, np->g_ty == ET_U ?
  3331.             bops[i].u_op : bops[i].s_op);
  3332.         r = fix2ops(np, bops[i].opflags);
  3333.         cc_hack(np);
  3334.         return r;
  3335.     case FIELDAS:
  3336.         return fldasn(np, flags);
  3337.     default:
  3338.         printf("Weird b_eval %s ", np->n_name);
  3339.         return FAIL;
  3340.     }
  3341. }
  3342.  
  3343. as_eval(np)
  3344. register NODEP np;
  3345. {
  3346.     NODEP rp = np->n_right;
  3347.     register int op, i, r;
  3348.  
  3349.     rp = np->n_right;
  3350.  
  3351.     op = np->g_token;
  3352.     op -= ASSIGN 0;
  3353.     switch (op) {
  3354.  
  3355.     /* these get unfolded now */
  3356.     case '*':
  3357.             return fixamul(np, bops[0].opflags);
  3358.     case '/':
  3359.             return fixadiv(np, bops[1].opflags);
  3360.     case '%':
  3361.             return fixamod(np, bops[2].opflags);
  3362.     case '&':       i = 3;  goto doop;
  3363.     case '|':       i = 4;  goto doop;
  3364.     case '^':       i = 5;  goto doop;
  3365.     case '+':       i = 6;  goto doop;
  3366.     case '-':       i = 7;  goto doop;
  3367.     case DOUBLE '<':i = 8;  goto doop;
  3368.     case DOUBLE '>':i = 9;
  3369. doop:
  3370.         strcpy(np->n_name, np->g_ty == ET_U ?
  3371.             bops[i].u_op : bops[i].s_op);
  3372.         r = fix_asn(np, bops[i].opflags);
  3373.         cc_hack(np);
  3374.         return r;
  3375.  
  3376.     default:
  3377.         printf("Weird as_eval %s ", np->n_name);
  3378.         return FAIL;
  3379.     }
  3380. }
  3381.  
  3382. rinherit(np)
  3383. register NODEP np;
  3384. {
  3385.     register NODEP rp = np->n_right;
  3386.  
  3387.     np->g_token = rp->g_token;
  3388.     np->g_offs = rp->g_offs;
  3389.     np->g_rno = rp->g_rno;
  3390.     np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
  3391. }
  3392.  
  3393. argmod(np)
  3394. register NODEP np;
  3395. {
  3396.     int size = 0;
  3397.  
  3398.     if (np->g_token == ',') {
  3399.         np->g_type = EV_RL;
  3400.         size += argmod(np->n_right);
  3401.         size += argmod(np->n_left);
  3402.         return size;
  3403.     }
  3404.     size += onearg(np);
  3405.     return size;
  3406. }
  3407.  
  3408. onearg(np)
  3409. register NODEP np;
  3410. {
  3411.     int rv;
  3412.  
  3413.     /* hack small ICON */
  3414.     if (np->g_sz == 1 && np->g_token == ICON)
  3415.         np->g_sz = 2;
  3416.     /* hack push of 0 */
  3417.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  3418.         addcode(np, "\tclr.S\t-(sp)\n");
  3419.         return (int)np->g_sz;
  3420.     }
  3421.     /* hack push of #OREG */
  3422.     if (np->g_token == OREG && isimmed(np)) {
  3423.         np->g_flags &= ~IMMEDID;
  3424.         addcode(np, "\tpea\tA\n");
  3425.         return 4;
  3426.     }
  3427.  
  3428.     if (np->g_ty == ET_A) {
  3429.         rv = np->g_bsize;
  3430.         strpush(np);
  3431.         freetmps(np);
  3432.         free1(NULL,np);
  3433.         return rv;
  3434.     }
  3435.  
  3436.     switch (np->g_sz) {
  3437.     case 1:
  3438.         addcode(np,
  3439.            "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n");
  3440.         return 2;
  3441.     case 2:
  3442.         addcode(np,
  3443.            "\tmove.w\tA,-(sp)\n");
  3444.         return 2;
  3445.     default:
  3446.         addcode(np,
  3447.            "\tmove.l\tA,-(sp)\n");
  3448.         return 4;
  3449.     }
  3450. }
  3451.  
  3452. #define MAXD DRV_START
  3453. #define MAXA (ARV_START-AREG)
  3454. #define NEEDALL (MAXA*AREG + MAXD)
  3455.  
  3456. order(np)
  3457. register NODEP np;
  3458. {
  3459.     int l, r;
  3460.  
  3461.     switch (np->g_type) {
  3462.     case E_BIN:
  3463.         order(np->n_right);
  3464.         r = np->n_right->g_needs;
  3465.     case E_UNARY:
  3466.         order(np->n_left);
  3467.         l = np->n_left->g_needs;
  3468.         break;
  3469.     default:    /* leaf */
  3470.         np->g_type = EV_NONE;
  3471.         np->g_needs = 0;
  3472.         return;
  3473.     }
  3474.  
  3475.     if (np->g_type == E_UNARY) {
  3476.         switch (np->g_token) {
  3477.         case STAR:
  3478.             np->g_needs = merge(l,AREG);
  3479.             break;
  3480.         case '(':
  3481.             np->g_needs = NEEDALL;
  3482.             break;
  3483.         case POSTINC:
  3484.         case POSTDEC:
  3485.         case '!':
  3486.             np->g_needs = merge(l,1);
  3487.             break;
  3488.         case '.':
  3489.             if (np->g_fldw) {
  3490.                 np->g_needs = merge(l,1);
  3491.                 break;
  3492.             }
  3493.             /* else fall through */
  3494.         default:
  3495.             np->g_needs = l;
  3496.         }
  3497.         np->g_type = EV_LEFT;
  3498.         return;
  3499.     }
  3500.  
  3501. /* at this point, have binary node */
  3502.  
  3503.     switch (np->g_token) {
  3504.     case DOUBLE '&':
  3505.     case DOUBLE '|':
  3506.     case '?':
  3507.     case ':':
  3508.         /* always left-right, no extra regs */
  3509.         np->g_type = EV_LRSEP;
  3510.         np->g_needs = merge(1, merge(l,r));
  3511.         return;
  3512.     case ',':
  3513.         np->g_needs = merge(l, r);
  3514.         np->g_type = EV_LRSEP;
  3515.         return;
  3516.     case '(':
  3517.         np->g_needs = NEEDALL;
  3518.         break;
  3519.     case '^':
  3520.     case DOUBLE '<':
  3521.     case DOUBLE '>':
  3522.     case ASSIGN '/':
  3523.     case ASSIGN DOUBLE '<':
  3524.     case ASSIGN DOUBLE '>':
  3525.         np->g_needs = merge(bin(l,r), 2);
  3526.         break;
  3527.     default:
  3528.         np->g_needs = merge(bin(l,r), 1);
  3529.     }
  3530.  
  3531.     if (isassign(np->g_token) || np->g_token == '=')
  3532.         np->g_type = EV_RL;    /* NO PUSHER's on L */
  3533.     else
  3534.         np->g_type = worst_1st(l, r);
  3535.     flag_saves(np, l, r);
  3536. }
  3537.  
  3538. flag_saves(np, l, r)
  3539. NODEP np;
  3540. {
  3541.     NODEP *cpp;
  3542.     register int other;
  3543.  
  3544.     if (np->g_type == EV_LR) {
  3545.         cpp = &np->n_left;
  3546.         other = r;
  3547.     } else {
  3548.         cpp = &np->n_right;
  3549.         other = l;
  3550.     }
  3551.     if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
  3552.         addtmp(np, cpp);
  3553. }
  3554.  
  3555. addtmp(np, cpp)
  3556. NODEP np, *cpp;
  3557. {
  3558.     NODEP cp, tp;
  3559.     NODEP copyone();
  3560.  
  3561.     cp = *cpp;
  3562.     tp = copyone(cp);
  3563.     tp->n_left = cp;
  3564.     *cpp = tp;
  3565.     tp->g_token = PUSHER;
  3566.     strcpy(tp->n_name, "pusher");
  3567.     tp->g_type = EV_LEFT;
  3568. }
  3569.  
  3570. worst_1st(l,r)
  3571. {
  3572.     int ld, rd;
  3573.  
  3574.     ld = l & 7;
  3575.     rd = r & 7;
  3576.     if (rd > ld)
  3577.         return EV_RL;
  3578.     if (r > l)
  3579.         return EV_RL;
  3580.     return EV_LR;
  3581. }
  3582.  
  3583. bin(l,r)
  3584. {
  3585.     int la, ra, na;
  3586.     int ld, rd, nd;
  3587.  
  3588.     la = l/AREG;
  3589.     ra = r/AREG;
  3590.     ld = l & 7;
  3591.     rd = r & 7;
  3592.     na = la > ra ? la : ra;
  3593.     if (ld == rd)
  3594.         nd = ld == MAXD ? MAXD : ld+1;
  3595.     else
  3596.         nd = ld > rd ? ld : rd;
  3597.     return na*AREG + nd;
  3598. }
  3599.  
  3600. merge(need, have)
  3601. {
  3602.     int na, nd, ha, hd, xa, xd;
  3603.  
  3604.     na = need/AREG;
  3605.     ha = have/AREG;
  3606.     nd = need & 7;
  3607.     hd = have & 7;
  3608.     xa = na > ha ? na : ha;
  3609.     xd = nd > hd ? nd : hd;
  3610.     return xa*AREG + xd;
  3611. }
  3612.  
  3613. holdlbls(np)
  3614. NODEP np;
  3615. {
  3616.     np->g_bsize = new_lbl();
  3617.     new_lbl();
  3618. }
  3619.  
  3620. rinhlbls(np)
  3621. NODEP np;
  3622. {
  3623.     np->g_bsize = np->n_right->g_bsize;
  3624. }
  3625.  
  3626. /* limited version of same address check
  3627.     assume one of these is a temp register */
  3628. same_a(p1, p2)
  3629. NODEP p1, p2;
  3630. {
  3631.     if (p1->g_token != p2->g_token)
  3632.         return 0;
  3633.     if (p1->g_rno != p2->g_rno)
  3634.         return 0;
  3635.     return 1;
  3636. }
  3637.  
  3638. optadd(np, flags, sign)
  3639. register NODEP np;
  3640. {
  3641.     NODEP lp = np->n_left, rp = np->n_right;
  3642.  
  3643.     if (rp->g_token != ICON)
  3644.         return 0;
  3645.     if (isimmed(lp) && isimmed(rp)) {
  3646.         switch (lp->g_token) {
  3647.         case OREG:
  3648.         case ONAME:
  3649.             inherit(np);
  3650.             if (sign == -1)
  3651.                 rp->g_offs = -rp->g_offs;
  3652.             np->g_offs += rp->g_offs;
  3653.  
  3654.             if ((flags & IMMA_OK) == 0)
  3655.                 imm_oreg(np);
  3656.             return 1;
  3657.         default:
  3658.             return 0;
  3659.         }
  3660.     }
  3661.     return 0;
  3662. }
  3663.  
  3664. iscc(np)
  3665. NODEP np;
  3666. {
  3667.     return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
  3668. }
  3669.  
  3670. cc_hack(np)
  3671. NODEP np;
  3672. {
  3673.     if (isareg(np))
  3674.         return;
  3675.     np->g_flags |= SIDE_CC;
  3676. }
  3677.  
  3678. cctok(np)
  3679. NODEP np;
  3680. {
  3681.     if (np->g_token >= BR_TOK)
  3682.         return np->g_token - BR_TOK;
  3683.     if (np->g_flags & SIDE_CC)
  3684.         return B_NE;
  3685.     printf("cctok error ");
  3686.     return 0;
  3687. }
  3688. SHAR_EOF
  3689. #    End of shell archive
  3690. exit 0
  3691. -- 
  3692. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  3693. Have five nice days.
  3694.